2

I've a transaction in Hibernate. I save an object usign session.save() and other using session.getNamedQuery().executeUpdate(). The problem is that the second object depends on existence of first, but even when both calls are on the same transaction, the first object "still doesn't exists" when I try to insert using the namedQuery. If I flush() the session it works, but I don't now if it is a good practice to manipulate the session like that.

Session session = HibernateSessionManager.getSessionFactory().getCurrentSession();
Transaction transaction = null;
   try {
         transaction = session.beginTransaction();
         session.save(myObjectToSave);
         session.flush(); //only works with this line in between
         session.getNamedQuery("ar.com.portal.bean.Application.insertLang").executeUpdate();
         transaction.commit();
      } catch (Exception e) {
          if (transaction != null) transaction.rollback();
          throw e;
      } 

Is that the correct solution? or that depends on some configuration parameter? I'm new to Hibernate.

Edit:

These are the properties that I've in my hibernate.cfg.xml

<property name="connection.pool_size">10</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">true</property>

Contents of namedQuery

<sql-query  name="insertLang" >
insert into APPLICATION_LANG (APPLICATION_ID, ISO_LANGUAGE_ID, WORKSPACE_ID, NAME, DESCRIPTION)
values ( :id, :lang, :systemObject.workspace.id, :name, :description)
</sql-query >

1 Answers1

1

Hibernate does not flush anything before executing native SQL queries. Note that this is not the case with HQL because Hibernate knows which entities are used in the query, so it can perform necessary flushing automatically before query execution. See this blog for more details.

So, you can solve the issue the way you already did it (explicitly flush everything before the query), or you can define the synchronized entity class:

((SQLQuery) session.getNamedQuery("..."))
  .addSynchronizedEntityClass(MyObjectToSaveClass.class)
  .executeUpdate();

The latter approach is better because it will not perform any flushing if there are no pending (unflushed) DML changes related to MyObjectToSaveClass entities and because it will not invalidate the entire second level cache (see this answer for more details).

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110