java - Hibernate - Setting null in entity collection is automatically persisted at transaction commit -
due architecture requirements can't use our hibernate entities dtos, use dozer transform entities pojos.
our typical service looks this:
@transactional(readonly=true) @override public task loadtask(int taskid){ taskentity taske = taskdao.load(taskid); if (taske != null){ taske.setattachments(null) task task = objectmapper.convert(taske, task.class); return task; }else{ return null; } }
as can see, before transforming taskentity task set attachments null. because attachments lazy collection , don't want unnecessarily trigger loading of entities.
before updating spring 4.1.1 worked without problem. however, upgraded spring 3.2.7, leaving hibernate @ 3.6.10. then, when executing same code noticed hibernate executing statement after loadtask execution:
update taskattachment set taskid = null id= ?
that say, because of setting null in taskentity.attachments, hibernate deletes foreign key in taskattachment.
configuration properties: spring.transactionmanager_class=org.springframework.transaction.jta.websphereuowtransactionmanager hibernate.transaction.manager_lookup_class=org.hibernate.transaction.websphereextendedjtatransactionlookup hibernate.current_session_context_class=jta hibernate.transaction.factory_class=org.hibernate.transaction.jtatransactionfactory jta.usertransaction=java:comp/usertransaction
session factory config
<bean id="mainsessionfactory" class="org.springframework.orm.hibernate3.annotation.annotationsessionfactorybean"> <property name="jtatransactionmanager" ref="jtatransactionmanager" /> <property name="datasource" ref="maindatasource" /> <property name="packagestoscan" ref="packages-mainsessionfactory" /> <property name="hibernateproperties" ref="properties-mainsessionfactory" /> </bean>
the orm-related thing changed stopped using hibernatetemplate in favour sessionfactory.getcurrentsession().
our former basedao:
public abstract class basedao<entitytype extends baseentity<idtype>, idtype extends serializable> extends hibernatedaosupport public basedao(hibernatetemplate hibernatetemplate, class<entitytype> clazz){ super(); super.sethibernatetemplate(hibernatetemplate); this.clazz= clazz; } public entitytype load(idtype id){ return gethibernatetemplate().get(clazz, id); }
our current basedao:
@suppresswarnings("unchecked") public abstract class basedao<entitytype extends baseentity<idtype>, idtype extends serializable> implements ibasedao<entitytype, idtype>{ private class<entitytype> clazz; private sessionfactory sessionfactory; public basedao(sessionfactory sessionfactory, class<entitytype> clazz){ super(); this.clazz= clazz; this.sessionfactory=sessionfactory; } public entitytype load(idtype id){ return (entitytype)getsession().get(clazz, id); } protected session getsession(){ return sessionfactory.getcurrentsession(); }
update: it's not spring version related issue. have checked using hibernatetemplate.get() doesn't persist null, , sessionfactory.getcurrentsession().get() does, why?
@transactional(readonly=true)
tells spring operation not modifying db, in such case sets connection read-only , hibernate not update entity. if remove readonly=true
see using hibernatetemplate.get()
change persisted.
if use sessionfactory.getcurrentsession()
you're circumventing spring's initialization part sets session readonly , therefore changes persisted.
relying in readonly=true
inhibit updates not practice because not supported dbs , orms. best course of action using session.evict()
detach entity. anyway keep readonly=true
because if db/orm supports db access optimized read-only operations.
Comments
Post a Comment