-->
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.  [ 6 posts ] 
Author Message
 Post subject: think I need merge operation but merge not updating Ids
PostPosted: Tue Aug 15, 2006 8:03 am 
Newbie

Joined: Tue May 02, 2006 12:32 pm
Posts: 8
Hibernate version: Hibernate 3.2.0.cr2
Hibernate Annotations 3.2.0.cr1
Spring 1.2.7

Name and version of the database you are using:
MySql

This is an unusual problem we are having, and I would very much appreciate some help :-

1) We have a situation where we seem to need to use merge() rather than saveOrUpdate() to persist a graph of of entities (Parent Entity with oneToMany assocation of child entities)

- We send transfer objects back to our client tier.
- When the modified TOs come back to the server tier they get translated as is into Hibernate Entity classes - effectively detached as this point (we can't change this architectural decision).
- We use Spring hibernateDAOSupport to call merge() on the parent entity. The parent entity has a oneToMany association to a child entity e.g.

@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY )
@JoinColumn(name = "circumstancesFk")
@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
public List<ApplicantDO> getApplicants() {
return applicants;
}

Previously it was the DELETE_ORPHAN that wasn't working until we used merge(). If we used a saveOrUpdate() hibernate did not detect any orphans that had been removed from the child collection - updates and inserts all worked but NOT child deletes.

Using merge() meant we could see that Hibernate would re-select the entity and then detect the deleted child orphans :-)
(reading the hibernate docs I see the quote re: merge operation:- "if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance" )

Hibernate now issues the delete (for the object that was deleted for the TO collection and therefore missing from the Entity Collection).


2) Using merge() is now causing us a problem in that the operation that uses merge() must also provide functionality to INSERT the entity graph as well. If the TOs and Entities have a primary key of null the INSERT is correctly performed, however we have found that the merged Entity is not updated with its new primary key values or version.

We have tried catching the returned object e.g.

circumstances = (CircumstancesDO) getHibernateTemplate().merge(circumstances);

however this doesn't seem to update the Id in the returned object.

I notice that the docs for a merge() operation state
"Note that merge will not update the identifiers in the passed-in object graph (in contrast to TopLink)! Consider registering Spring's IdTransferringMergeEventListener if you'd like to have newly assigned ids transferred to the original object graph too."

So I tried the registering the IdTransferringMergeEventListener on the session but it didn't seem to make any difference. But I did note that IdTransferringMergeEventListener javadocs state :-

"NOTE: Due to incompatible changes in the Hibernate 3.1 event listener API (according to the Hibernate 3.1 RC1 release that was available at the time of this writing), this merge event listener will currently only work as-is with Hibernate 3.0. Consider copying this implementation and adapting it to the changed API if you want to run it against Hibernate 3.1"

I looked into setting up my own IdTransferringMergeEventListener based on the old Spring one, but the API for :-

DefaultMergeEventListener
protected void entityIsTransient(MergeEvent event, Map copyCache)

has changed such that I cannot get the mergedCopy anymore e.g.

Object mergedCopy = super.entityIsTransient(event, copyCache);

is needed, but not possible as
super.entityIsTransient(event, copyCache);

now returns void.

Questions :-

- Is there a better solution to the delete orphan issue with detached objects? I like having a single operation that copes with both inserts/updates/deletes but this seems difficult when using detached objects ?

- How can I get a Hibernate 3.2 compatible verison of IdTransferringMergeEventListener working ?


many thanks


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 15, 2006 8:40 am 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
There is a Hibernate 3.1+ version of IdTransferringMergeEventListener in Spring2, RC3 was just released. There seems to be no backwards compatibility issues otherwise.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 15, 2006 10:35 am 
Newbie

Joined: Tue May 02, 2006 12:32 pm
Posts: 8
Thanks Ananasi, but still not there yet, I added the
IdTransferringMergeEventListener from latest Spring RC, but get :-

14:42:36,949 DEBUG [AbstractSaveEventListener] delaying identity-insert due to no transaction in progress

in the IdTransferringMergeEventListener, it finds that the id is null i.e.

Serializable id = persister.getIdentifier(event.getResult(), session.getEntityMode());

gets null id.


We are using EJB3 Session Beans with Hibernate 3 Entities (via Hibernate Session not EJB3 entity manager) - so Transactions are demarcated in EJB3 SSB using annotation, I believe they are working ok, because the datasource is TX aware.

So how is IdTransferringMergeEventListener supposed to work ? i.e. in situations where there is a transaction vs. no transaction ?

Also do I need to do anything else to make Hibernate Session aware of the EJB3 container transaction? or is using TX aware datasource enough?

Full log :-

14:42:21,621 DEBUG [SessionImpl] opened session at timestamp: 4733539703279616
14:42:36,949 DEBUG [AbstractSaveEventListener] delaying identity-insert due to no transaction in progress
14:42:48,606 DEBUG [AbstractFlushingEventListener] processing flush-time cascades
14:42:48,606 DEBUG [AbstractFlushingEventListener] dirty checking collections
14:42:48,606 DEBUG [AbstractFlushingEventListener] Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects
14:42:48,606 DEBUG [AbstractFlushingEventListener] Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
14:42:48,606 DEBUG [Printer] listing entities:
14:42:48,606 DEBUG [Printer] com.rdf.mform.domain.user.ExistingMortgageDetailsDO{monthlyPayment=component[currency,amount]{amount=49900, currency=GBP}, propertyLocation=England, loanAmount=component[currency,amount]{amount=50000000, currency=GBP}, loanAmountInterestPart=component[currency,amount]{amount=0, currency=GBP}, repaymentType=Repayment, dealType=DiscountedVariable, latestVersion=0, id=null, loanAmountRepaymentPart=null, loanTermYears=10}
14:42:48,606 DEBUG [AbstractBatcher] about to open PreparedStatement (open PreparedStatements: 0, globally: 1)
14:42:48,606 DEBUG [ConnectionManager] opening JDBC connection
14:42:48,606 DEBUG [SQL] insert into existing_mortgage_details (latestVersion, repaymentType, loanAmountCur, loanAmount, loanTermYears, propertyLocation, loanAmountRepaymentPartCur, loanAmountRepaymentPart, loanAmountInterestPartCur, loanAmountInterestPart, dealType, monthlyPaymentCur, monthlyPayment) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
14:42:48,606 INFO [STDOUT] Hibernate: insert into existing_mortgage_details (latestVersion, repaymentType, loanAmountCur, loanAmount, loanTermYears, propertyLocation, loanAmountRepaymentPartCur, loanAmountRepaymentPart, loanAmountInterestPartCur, loanAmountInterestPart, dealType, monthlyPaymentCur, monthlyPayment) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
14:42:48,606 DEBUG [IdentifierGeneratorFactory] Natively generated identity: 1003
14:42:48,606 DEBUG [AbstractBatcher] about to close PreparedStatement (open PreparedStatements: 1, globally: 2)
14:42:48,606 DEBUG [ConnectionManager] releasing JDBC connection [ (open PreparedStatements: 0, globally: 1) (open ResultSets: 0, globally: 0)]
14:42:48,622 DEBUG [ConnectionManager] transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 15, 2006 10:47 am 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
What PlatformTransactionManager is configured in Spring? I'm assuming JtaTransactionManager, yes? Could you post appropriate snippets of the Spring configuration file, wrt the transaction setup. And example of the annotated method.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 15, 2006 11:59 am 
Newbie

Joined: Tue May 02, 2006 12:32 pm
Posts: 8
I originally had no transactionManager specified, as we believed that EJB3 was managing transaction start, HibernateSession was using the tx aware datasource associated with the thread. We thought we only needed to configure JTA if using > 1 database etc.

Anyhow, I have just tried configuring JTA (we're using JBoss), but I get the same result - in that the IdTransferringMergeEventListener still gets id of null.


application context snipped :-

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName"><null/></property>
<property name="transactionManagerName">
<value>java:/TransactionManager</value>
</property>
</bean>

<bean id="hibernateSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="mformDS" />
<property name="annotatedClasses" ref="annotatedClassesList">
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.query.factory_class">
org.hibernate.hql.classic.ClassicQueryTranslatorFactory
</prop>
<prop key="hibernate.show_sql">£{hibernate.show_sql}</prop>
</props>
</property>
<property name="eventListeners">
<map>
<entry>
<key>
<value>pre-update</value>
</key>
<ref bean="validatePreUpdateEventListener"/>
</entry>
<entry>
<key>
<value>pre-insert</value>
</key>
<ref bean="validatePreInsertEventListener"/>
</entry>
<entry key="merge">
<bean class="com.rdf.infra.spring.hibernate3.support.IdTransferringMergeEventListener"/>
</entry>
</map>
</property>
</bean>

EJB3 transaction annotations :-

import javax.ejb.TransactionAttribute;

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public SearchCriteriaDTO saveSearchCriteria(String userId, SearchCriteriaDTO searchCriteria) {
return getDelegateBean().saveSearchCriteria(userId, searchCriteria);
}

thanks for your time.

In the log I can see the JTA mgr :-

16:47:54,060 INFO [JtaTransactionManager] Using JTA UserTransaction: org.springframework.transaction.jta.UserTransactionAdapter@735a55
16:47:54,060 INFO [JtaTransactionManager] Using JTA TransactionManager: org.jboss.tm.TxManager@12faeca
16:47:54,278 INFO [Version] Hibernate Annotations 3.2.0.CR1
16:47:54,310 INFO [Environment] Hibernate 3.2 cr2
16:47:54,310 INFO [Environment] loaded properties from resource hibernate.properties: {hibernate.bytecode.use_reflection_optimizer=false}

but then get :-

16:48:14,763 DEBUG [AbstractSaveEventListener] delaying identity-insert due to no transaction in progress

16:48:24,716 DEBUG [AbstractFlushingEventListener] processing flush-time cascades
16:48:24,716 DEBUG [AbstractFlushingEventListener] dirty checking collections
16:48:24,716 DEBUG [AbstractFlushingEventListener] Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects
16:48:24,716 DEBUG [AbstractFlushingEventListener] Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
16:48:24,716 DEBUG [Printer] listing entities:
16:48:24,731 DEBUG [Printer] com.rdf.mform.domain.user.ExistingMortgageDetailsDO{monthlyPayment=component[currency,amount]{amount=49900, currency=GBP}, propertyLocation=England, loanAmount=component[currency,amount]{amount=50000000, currency=GBP}, loanAmountInterestPart=component[currency,amount]{amount=0, currency=GBP}, repaymentType=Repayment, dealType=DiscountedVariable, latestVersion=0, id=null, loanAmountRepaymentPart=null, loanTermYears=10}
16:48:24,731 DEBUG [AbstractBatcher] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
16:48:24,731 DEBUG [ConnectionManager] opening JDBC connection
16:48:24,731 DEBUG [SQL] insert into existing_mortgage_details (latestVersion, repaymentType, loanAmountCur, loanAmount, loanTermYears, propertyLocation, loanAmountRepaymentPartCur, loanAmountRepaymentPart, loanAmountInterestPartCur, loanAmountInterestPart, dealType, monthlyPaymentCur, monthlyPayment) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
16:48:24,731 INFO [STDOUT] Hibernate: insert into existing_mortgage_details (latestVersion, repaymentType, loanAmountCur, loanAmount, loanTermYears, propertyLocation, loanAmountRepaymentPartCur, loanAmountRepaymentPart, loanAmountInterestPartCur, loanAmountInterestPart, dealType, monthlyPaymentCur, monthlyPayment) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
16:48:24,747 DEBUG [IdentifierGeneratorFactory] Natively generated identity: 1002
16:48:24,747 DEBUG [AbstractBatcher] about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
16:48:24,747 DEBUG [ConnectionManager] releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
16:48:24,762 DEBUG [ConnectionManager] transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 15, 2006 12:50 pm 
Expert
Expert

Joined: Tue Jul 11, 2006 10:21 am
Posts: 457
Location: Columbus, Ohio
Sorry, you've reached the limit of my knowledge wrt EJB3/JBoss/Annotations. There seems to be several posts in the Spring forums regarding the transaction setup and EJB3 with Hibernate, so maybe try there as well. Sorry I couldn't help of more help, good luck!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.