The problem with JPA Composite primary keys and CascadeType.ALL

Following my previous blog here, I encountered another issue with the use of composite primary keys.

With JPA, we can specify the cascade of relationship to be CascadeType.ALL, so that when we persist the CUSTOMER, all of its PRODUCT are persisted too.

So, the code will be modified as follows:

CUSTOMER

package com.wordpress.dwuysan;

// imports omitted

@Entity
@Table(name = "customer")
public class Customer implements Serializable {
    @Id
    @Column(name = "customer_id")
    private String customerId;

    @OneToMany(
        fetch = FetchType.EAGER,
        mappedBy = "customer",
        cascade = CascadeType.ALL)
    private Set<Product> products = new HashSet<Product>();

    /* the rest of the code omitted */
}

During unit testing however, when executing the following lines:

    this.entityManager.persist(customer); // customer with child products here
    final Query query = this.entityManager.createQuery("FROM Customer cust");
    return query.getResultList(); // error here

And the error is:

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
	at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:637)
	at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:74)
	at com.wordpress.dwuysan.CustomerServiceBean(CustomerServiceBean.java:59)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)

SO, for now, I think I will use another ID for the PRODUCT. Would need to look for the underlying reason.

Advertisements