Hi all,
Let me start by saying that I am relantively new to using Hibernate more so Hibernate annotations. In saying that as most developers have experienced I've have had to work things out by myself through trial and error and little home projects - however there is only some much one can learn before we have to start asking around, for me, that misunderstanding is around the Hibernate exception of NonUniqueObjectException. The scenario is as follows:
I have 2 classes InvestmentTransaction.java and InitialFeeTransaction.java:
Code:
@Entity
@MappedSuperclass
public class InvestmentTransaction extends ProductTransaction {
@OneToOne
@Cascade( {org.hibernate.annotations.CascadeType.ALL})
@JoinColumn(name = "ClientPaymentId")
private InitialFeeTransaction initialFeeTransaction
...
Code:
@Entity
@DiscriminatorValue(value = "UFB")
public final class InitialFeeTransaction extends ProductTransaction {
@OneToOne
@Cascade( {org.hibernate.annotations.CascadeType.ALL})
@JoinColumn(name = "ClientPaymentId")
private InvestmentTransaction investmentTransaction;
...
As you can see from the class structure that an InvestmentTransaction can have a InitialFeeTransaction and vice versa. The reason behind this is when we save/update/delete and investment transaction we want to update the initial fee transaction and vice versa.
Subsequently my question is as follows:
After implementing the classes I noticed I can save/update/delete perfectly without any exceptions then I implemented transaction managment on the DAOs and the Services that access these classes:
applicationContext-dao.xml
Code:
<bean id="productTransactionDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="target">
<bean id="productTransactionDaoImpl" class="za.co.aforbes.fpc.db.dao.client.impl.hibernate.ProductTransactionDaoImpl">
<property name="sessionFactory">
<ref bean="ifaSessionFactory" />
</property>
</bean>
</property>
</bean>
and the applicationContext-service:
Code:
<bean id="productTransactionServiceTransaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="target">
<ref bean="productTransactionService" />
</property>
</bean>
Now if I used the service to save the record, the records are saved successfully within a transaction without any exceptions. HOWEVER, if I delete an investment transaction I get the following exception:
Code:
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [za.co.aforbes.fpc.db.model.client.InitialFeeTransaction#9137144]
at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:613)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:121)
at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74)
at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:794)
at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:772)
at org.springframework.orm.hibernate3.HibernateTemplate$25.doInHibernate(HibernateTemplate.java:852)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
So after some messing around I found out that if I don't reference the the classes and manually handle saving/updating/deleting then this resolves this problem - but i feel this is incorrect and makes life that much harder as now i have to remember when i save an investment tranascation go save the initial fee transaction... problematic and a maintenance nightmare?!
I also noticed if i comment out the transaction property for the service:
Code:
<!-- <prop key="delete*">PROPAGATION_REQUIRED</prop> -->
That also resolves the issue - BUT i want transaction management - because if something fails in the delete method i want to rollback all actions.
Any feedback would be appreciated.
Thanks Justin