I have a domain that uses InheritanceType.JOINED so I have a master class with 2 sub classes using the table per class strategy with a discriminator column.
Master Class Item:
@Entity
@Table(name = "item")
@Inheritance(strategy = Inheritance.JOINED)
@DiscriminatorColumn(name = "TYPE")
public abstract class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "type")
private String type;
// other properties, getters, and setters
}
Sub Class CD:
@Entity
@Table(name = "cd")
@DiscriminatorValue("CD")
public class CD extends Item {
@Enumerated(EnumType.STRING)
private Genre genre
public static enum Genre {
CLASSICAL, ROCK, BLUES, POP;
}
// other properties, getters and setters
}
Sub Class Book
@Entity
@Table(name = "book")
@DiscriminatorValue("BOOK")
public class Book extends Item {
@Enumerated(EnumType.STRING)
private Genre genre
public static enum Genre {
HISTORY, MYSTERY, NOVEL, COMPUTER_SCIENCE;
}
// other properties, getters and setters
}
I would like to be able to use the QueryDSL QueryDslPredicateExecutor because I need to return a Page result of the Item class but by performing a search of each of the sub class tables on their respective genre property.
I know that in with Spring JPA using JPQL I can do the following and it works:
@Query(value = "SELECT DISTINCT(item) FROM Item item"
+ " WHERE item.id IN(SELECT cd.id FROM CD cd WHERE cd.genre IN('ROCK','BLUES'))" + " OR item.id IN(SELECT book.id FROM Book book WHERE book.genre IN('HISTORY'))"
I have tried to do this using QueryDSL, but I am not having any success. This was my last attempt:
I first created a BooleanBuilder like this:
BooleanBuilder builder = new BooleanBuilder();
My ItemRepository interface looks like this:
public interface ItemRepository extends JpaRepository<Item, Long>, QueryDslPredicateExecutor<Item> {
}
But when I attempt to perform the query with:
Page<Item> itemPage = itemRepository.findAll(builder, new PageRequest(0, 10));
I get an error and I have included the whole stackTrace below. Basically, it isn't trying to search the Book.Genre genre, only the CD.Genre genre property.
Is it possible to perform a repository query with multiple ORs combining queries for each of the sub classes?
I would be grateful for any help with this.
By the way here are the versions that I am using:
Spring Boot 1.3.2.RELEASE
querydsl-jpa:
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>3.7.2</version>
</dependency>
build plugin:
<!-- QueryDsl -->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/apt</outputDirectory>
<processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>3.7.2</version>
</dependency>
</dependencies>
</plugin>
Sincerely,
Frank Castro
stack trace:
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [HISTORY] did not match expected type [com.facm.demo.domain.CD$Genre (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [HISTORY] did not match expected type [com.facm.demo.domain.CD$Genre (n/a)] at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:384)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:227)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:131)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy174.findAll(Unknown Source)
at com.facm.demo.repository.ItemRepositoryTest.testQueryDsl(ItemRepositoryTest.java:274)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.IllegalArgumentException: Parameter value [HISTORY] did not match expected type [com.facm.demo.domain.CD$Genre (n/a)] at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:874)
at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:80)
at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:248)
at org.hibernate.jpa.internal.QueryImpl$JpaPositionalParameterRegistrationImpl.bindValue(QueryImpl.java:337)
at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:674)
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:198)
at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:49)
at com.mysema.query.jpa.impl.JPAUtil.setConstants(JPAUtil.java:55)
at com.mysema.query.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:130)
at com.mysema.query.jpa.impl.AbstractJPAQuery.count(AbstractJPAQuery.java:81)
at org.springframework.data.jpa.repository.support.QueryDslJpaRepository.findAll(QueryDslJpaRepository.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:483)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:468)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:440)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 38 more