Это просто упражнение, чтобы понять, как использовать CriteriaBuilder и EntityManager с объединением. Я хочу присоединиться к классу Product с Customer и выбрать каждый продукт с запрошенным идентификатором customer.
У меня есть класс Product и Customer следующим образом:
@Entity
public class Product {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne(optional = false)
@JoinColumn(name = "customer_id", nullable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
private Customer customer;
...
}
And Customer:
@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
...
}
По сути, я хочу того, чего бы я мог легко достичь с помощью этого интерфейса:
public interface ProductRepository extends JpaRepository<Product, String>{
List<Product> findByCustomerId(Long custsomerId);
}
Я безуспешно пытался выполнить следующее:
public class ProductRepositoryCustomImpl implements ProductRepositoryCustom {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> join(Long customerId) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Product> cq = cb.createQuery(Product.class);
Root<Product> from = cq.from(Product.class);
Metamodel m = em.getMetamodel();
EntityType<Customer> CustomerMeta = m.entity(Customer.class);
Join<Product, Customer> join = from.join(CustomerMeta.getId(Customer.class));
ParameterExpression<Long> p = cb.parameter(Long.class);
CriteriaQuery<Product> query = cq.multiselect(join).where(cb.equal(join.get("customer_id"), p));
TypedQuery<Product> typedQuery = em.createQuery(query);
typedQuery.setParameter(p, customerId);
List<Product> results = typedQuery.getResultList();
return results;
}
}
Я получаю эту ошибку:
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:821) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:802) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at com.jpa.jpaExample.JpaExampleApplication.main(JpaExampleApplication.java:19) [classes/:na]
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Attribute [com.jpa.jpaExample.Customer#id : java.lang.Long] not castable to requested type [com.jpa.jpaExample.Customer]; nested exception is java.lang.IllegalArgumentException: Attribute [com.jpa.jpaExample.Customer#id : java.lang.Long] not castable to requested type [com.jpa.jpaExample.Customer]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:367) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527) ~[spring-orm-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) ~[spring-data-jpa-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at com.sun.proxy.$Proxy75.join(Unknown Source) ~[na:na]