Hi,
We have a Customer entity with Address objects embedded into it for saving. The Address entity itself has a PK class AddressPK which is implemented using @Embeddable.
Address has the CLIENT_ID(Primary key of customer) and ADDR_TYPE forming its composite key. Reason being a single customer can have multiple addresses.
The problem being faced is while persisting the customer which also contains embedded addresses in it. The addresses are not able to get saved as the just generated CLIENT_ID of customer is not available to the addresses for persisting.
Hibernate version:3.2.1.ga
Mapping documents:
@Entity
@Table(name="P_CRM_CLIENT_MASTER")
public class Customer
{
private Long customerId;
protected String firstName;
protected String lastName;
........
protected Collection<Address> addresses = new ArrayList<Address>();
@Id
@GeneratedValue (strategy=GenerationType.AUTO)
@Column (name = "CLIENT_ID")
public Long getCustomerId(){
return customerId;
}
public void setCustomerId(Long customerId)
{
this.customerId = customerId;
}
//....getters and setters for firstName and lastName
@OneToMany (mappedBy = "customer", cascade=CascadeType.ALL, fetch = FetchType.EAGER)
public Collection<Address> getAddresses()
{
return addresses;
}
public void setAddresses(Collection<Address> addresses)
{
this.addresses = addresses;
}
public void addAddress(Address address)
{
this.addresses.add(address);
address.setCustomer(this);
}
}
.................
@Entity
@Table(name="P_CRM_CLIENT_ADDRESS")
public class Address
{
protected AddressPK addressPK;
protected Customer customer;
protected String addressLine1;
protected String addressLine2;
protected String addressLine3;
@Id
@AttributeOverrides({
@AttributeOverride(name = "customerId", column = @Column(name="CLIENT_ID")),
@AttributeOverride(name = "addressType", column = @Column(name="ADDR_TYPE"))
})
public AddressPK getAddressPK() {
return this.addressPK;
}
public void setAddressPK(AddressPK addressPK) {
this.addressPK = addressPK;
}
@ManyToOne
@JoinColumn (name = "CLIENT_ID", insertable=false, updatable=false)
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
//....getters and setters for addressLine1, addressLine2, addressLine3
....................
}
@Embeddable
public class AddressPK implements java.io.Serializable{
/** Creates a new instance of AddressPK */
public AddressPK() {
}
protected Long customerId;
protected String addressType;
public String getAddressType() {
return addressType;
}
public void setAddressType(String addressType) {
this.addressType = addressType;
}
public Long getCustomerId() {
return this.customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
//equals and hashcode implemented..
}
in the test class....
public void testSaveCustomer() throws Exception {
Customer cust = new Customer();
cust.setFirstName("Ricky");
cust.setLastName("Ponting");
AddressPK pk1 = new AddressPK();
pk1.setAddressType("HOM");
Address address = new Address();
address.setAddressLine1("Malleshwaram");
address.setAddressLine2("College Rd");
address.setAddressLine3("");
address.setAddressPK(pk1);
cust.addAddress(address);
AddressPK pk2 = new AddressPK();
address2.setAddressLine1("Indiranagar");
address2.setAddressLine2("Double Rd");
address2.setAddressLine3("");
pk2.setAddressType("VAC");
cust.addAddress(address2);
mgr.saveCustomer(cust);
/* the save method that will be called---->
public void save(T object) {
Object objId = LiteDaoUtils.getPersistentId(object);
log.debug("***** OBJECT ID IS ******"+objId);
if (objId == null) {
log.debug("Persisting the object"+object);
this.entityManager.persist(object);
} else {
log.debug("Merging the object: " + object);
this.entityManager.merge(object);
}
//this.entityManager.persist(object);
}
*/
}
Code between sessionFactory.openSession() and session.close():
Full stack trace of any exception that occurs:
org.springframework.transaction.UnexpectedRollbackException: JPA transaction unexpectedly rolled back (maybe marked rollback-only after a failed operation); nested exception is javax.persistence.RollbackException: Error while commiting the transaction
Caused by: javax.persistence.RollbackException: Error while commiting the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:420)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:654)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:624)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:307)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
at $Proxy31.saveCustomer(Unknown Source)
Name and version of the database you are using: Oracle 10g
The generated SQL (show_sql=true):
Debug level Hibernate log excerpt:
DEBUG - CustomerManagerImpl.saveCustomer(65) | Saving customer:
com.abc.dao.jpa.CustomerDaoImpl@18b3fee
DEBUG - CustomerDaoImpl.saveCustomer(64) | Customer being saved: Ricky,Ponting
DEBUG - LiteDaoUtils.getPersistentId(42) | 'public java.lang.Long com.abc.domain.model.Customer.getCustomerId()' was annotated as the identifier of 'com.abc.domain.model.Customer'
DEBUG - LiteDaoUtils.getPersistentId(56) | Persistent identity for object of type 'com.abc.domain.model.Customer' is accessible with method 'getCustomerId'
DEBUG - LiteGenericDaoJPA.save(70) | ***** OBJECT ID IS ******null
DEBUG - LiteGenericDaoJPA.save(73) | Persisting the objectRicky,Ponting
WARN - JDBCExceptionReporter.logExceptions(77) | SQL Error: 1400, SQLState: 23000
ERROR - JDBCExceptionReporter.logExceptions(78) | ORA-01400: cannot insert NULL into ("PDB"."P_CRM_CLIENT_ADDRESS"."CLIENT_ID")
WARN - JDBCExceptionReporter.logExceptions(77) | SQL Error: 1400, SQLState: 23000
ERROR - JDBCExceptionReporter.logExceptions(78) | ORA-01400: cannot insert NULL into ("PDB"."P_CRM_CLIENT_ADDRESS"."CLIENT_ID")
ERROR - AbstractFlushingEventListener.performExecutions(301) | Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:139)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:420)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:654)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:624)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:307)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
at $Proxy31.saveCustomer(Unknown Source)
at com.abc.service.impl.CustomerManagerImplTest.testSaveCustomer(CustomerManagerImplTest.java:125)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:164)
at junit.framework.TestCase.runBare(TestCase.java:130)
at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:69)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.framework.TestSuite.runTest(TestSuite.java:230)
at junit.framework.TestSuite.run(TestSuite.java:225)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:210)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:135)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:122)
at org.apache.maven.surefire.Surefire.run(Surefire.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:225)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:747)
Caused by: java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("PDB"."P_CRM_CLIENT_ADDRESS"."CLIENT_ID")
at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:367)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:9119)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
... 44 more
Tests run: 2, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.407 sec <<< FAILURE!
|