Hibernate session.update not working if not in transaction

Viewed 3556

My hibernate config:

Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.hbm2ddl.auto", "validate");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.id.new_generator_mappings", "false");
properties.put("hibernate.connection.autocommit", "true");
properties.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
properties.put("hibernate.connection.url", DBConnection.url);
properties.put("hibernate.connection.username", DBConnection.username);
properties.put("hibernate.connection.password", DBConnection.password);

Code example:

// pattern 1
Session s = sessionFactory.openSession();
ObjectA A = s.load(ObjectA.class, pk);
A.setAttr("abc");
s.update(A);
s.close();

// pattern 2
Session s = sessionFactory.openSession();
s.beginTransaction();
ObjectA A = s.load(ObjectA.class, pk);
A.setAttr("abc");
s.update(A);
s.close();

// pattern 3
Session s = sessionFactory.openSession();
Transaction tx = s.beginTransaction();
ObjectA A = s.load(ObjectA.class, pk);
A.setAttr("abc");
s.update(A);
tx.commit();
s.close();

Please ignore my compilation error. I am using hibernate in web application (without spring), and without using transaction, because I am using MySql database and MySql autocommit is true, so in turn, in hibernate, I make it as autocommit true as well. (I am using mysql-connector-java-5.1.23-bin.jar too).

Three of the pattern, I am only able to get pattern 3 works. I am totally confused now. I have few questions below:

1) I can't understand why pattern 1 is not working, all my select (via hibernate CriteriaBuilder or load) and insert (via hibernate session.save) works but only update doesn't work.

2) OK then I try using transaction like pattern 2, my hibernate auto-commit is true, so I assume when I close the session, the transaction should auto-commit but it doesn't work. Why?

3) Pattern 3 works, why I need transaction manager here? I want the jdbc to execute each single query in each transaction (one sql in one transaction), I don't worry the performance, but I have to include transaction here, why?

For pattern 1 and 2, I found that the update script is not even generated (based on hibernate log), the problem is not because script is generated but commit failed. Don't understand why? Please help...


PS:

Just wrap up some points for future reference after some trial and error:

1) Hibernate will only generate sql script upon the session.flush() is called but not tx.commit(), and session.flush() have to be called in Transaction block. without Transaction, it leads to exception. Explicit flush is not needed if the flush mode is auto, commit() will trigger flush.

2) Hibernate Transaction is not equivalent to database transaction, after some tries, I found that, if hibernate autocommit is false, yes, they are functionally equivalent and corresponding begin transaction script is generated via JDBC and send over to database (my guess only). If hibernate autocommit is true, no begin transaction is started although we declare it in hibernate Transaction tx = s.beginTransaction(), all the query will be autocommit and rollback will not work.

3) The reason of my case, session.save() (and also select) work without Transaction, it is a bit special because save have to be triggered in order to get the table identifier(primary key) and so sql script generated even without flush.

4) For pattern 2, I miss-understood, autocommit doesn't mean autocommit upon session closed, its true meaning should be autocommit upon each sql reach database. so pattern 2 will not work because there is no tx.commit, meaning there is no flush, so no sql script is generated. (whether tx.commit will be called automatically upon session.close, it depend on vendor implementation, some will be rollback.)

Conclusion, Transaction block is needed in Hibernate not matter what.

1 Answers
Related