-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: shared primary key annotations: Hibernate version:3.2.1.ga
PostPosted: Fri Apr 20, 2007 2:28 am 
Beginner
Beginner

Joined: Fri Apr 20, 2007 1:07 am
Posts: 23
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!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 23, 2007 1:20 am 
Newbie

Joined: Sun Apr 22, 2007 12:57 am
Posts: 7
For posting purpose, it is a lot easier to have public fields instead of getter and setters. The @Id annotation on Address class should be @EmbeddedId


Top
 Profile  
 
 Post subject: Same problem here
PostPosted: Thu Jan 31, 2008 4:45 pm 
Beginner
Beginner

Joined: Tue Jan 08, 2008 2:15 pm
Posts: 22
I have the same problem. Hard to find an answer anywhere.

TABLE A
----------
ID (generated)

TABLE B
----------
ID_OF_TABLE_A (part of PK, FK to Table A)
REST_OF_B_PK (part of PK)

Class A has a collection of Bs, mappedBy=association in class B

Class B has update=false,insert=false on association to A because
the FK is also part of the PK of table B.

Now, how can I tell hibernate with annotations that I want it to use the newly generated ID of Class A when it needs to insert into TABLE B as part of a cascaded save operation?

I have seen there is a PrimaryKeyJoinColumn(s) annotations - they don't seem to apply to this case (more for OneToOne or subclassing) - I tried PrimaryKeyJoinColumn, but HB did not consider it or even complained about the annotation.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.