JPA persistence doing an insert instead of update on entitymanager.merge()

5,944 views
Skip to first unread message

transmeta01

unread,
Nov 21, 2012, 1:50:18 PM11/21/12
to google...@googlegroups.com
I have DAO methods annotated with @Transactional as such:
public abstract class GenericDAO<T> implements DAO<T> {
private Class<T> persistentClass;
@PersistenceContext
EntityManager em;
public GenericDAO(EntityManager em, Class<T> persistentClass) {
this.persistentClass = persistentClass;
this.em = em;
}
public GenericDAO(Class<T> persistentClass) {
this.persistentClass = persistentClass;
}
@Transactional
@Override
public T persist(T t) {
em.persist(t);
return t;
}

@Transactional
@Override
public void delete(T t) {
em.remove(t);
em.flush();
}

@Transactional
@Override
public T update(T t) {
em.merge(t);
return t;
}

@Transactional()
@Override
public T merge(T t) {
em.merge(t);
return t;
}

@Override
public T findById(Long id) {
return em.find(persistentClass, id);
}
}

When I call merge, the DAO does an insert (new row), instead of doing an update. What is there a specific scope the persistence context must be in order to the update to be done? BTW, I have tried with adding em.flush() after the call to em.merge(), but did not solve the problem.

Thank

Wujek Srujek

unread,
Nov 21, 2012, 4:13:31 PM11/21/12
to google...@googlegroups.com
This is too little code to really say, the DAO itself is not enough, people normally needs some more context, but I suspect that the fact that you are ignoring the return value of merge might be causing your problems. The following scenario:
DomainObject do = new DomainObject(); // new state
dao.save(do); // here, the thing gets merged, which means a new instance is created and put in the persistence context and returned, and you ignore the returned result; unfortunately, do remains in new state, and it's the returned (and ignored) value that ist detached

do.setFoo(17);
dao.update(do); // here, you are not dealing with a detached instance, but again, a new one

Try to change the code so that the return value of merge does get used. Again, this is just a suspicion.

wujek


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-guice/-/bGD8mY4-G-0J.
To post to this group, send email to google...@googlegroups.com.
To unsubscribe from this group, send email to google-guice...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.

Richard Mutezintare

unread,
Nov 21, 2012, 6:21:55 PM11/21/12
to google...@googlegroups.com
good point about not returning the actual entity from merge method. I changed the method to return the result from merge(), however this did not solve the problem...


On Wed, Nov 21, 2012 at 4:13 PM, Wujek Srujek <wujek....@gmail.com> wrote:
here, the thing gets merged, which means a new instance is created an

I thought the entityManager would look at the id and if there is one, it would fetch the corresponding entity and then do the merging, if there is no id, then it is a persit() call? My problem may be because i essentially have no session, in the hibernate since, I suspect that a new persistence context is created by guice-persist every time, since my dao is not bound to a @Singleton scope...do this make since? In any case, I am investigating in that direction. Any alternate suggestions?

Thanks

Richard Mutezintare

unread,
Nov 21, 2012, 7:35:06 PM11/21/12
to google...@googlegroups.com
after debugging turns out the persistence context sticks, in the code snippet below: 

@Transactional
@Override
public T merge(T t) {
boolean isManager = em.contains(t);
System.out.print(isManager);
t = em.merge(t);
return t;
}

isManaged = true, and yet, an insert is still performed instead of an update...Then tried adding em.flush(), still to no avail. 

below is my persistence.xml file: (it's pretty vanilla)

<persistence-unit name="logbook-persistence" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>

<!-- transaction will be application managed in dev/test mode -->
<!-- <jta-data-source>java:/DefaultDS</jta-data-source> -->

<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<!-- <property name="javax.persistence.validation.mode" value="NONE" /> -->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/logbook" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="root" />
<property name="hibernate.connection.autocommit" value="true" />
<!-- <property name="hibernate.cache.use_query_cache" value="true"/> 
<property  name="hibernate.cache.use_second_level_cache" value="true"/> 
<property name="hibernate.cache.region.factory_class" 
value="org.hibernate.cache.infinispan.InfinispanRegionFactory"/> -->
<property name="hibernate.connection.provider_class" value="org.hibernate.connection.DriverManagerConnectionProvider" />
</properties>
</persistence-unit>
Reply all
Reply to author
Forward
0 new messages