GMsoF GMsoF -4 years ago 90
MySQL Question

Hibernate session.update not working if not in transaction

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.

Answer Source

I think you have a bit of confusion. The transaction (org.hibernate.transaction) is not exactly a DB transaction. Such Object are used by hibernate when you flush the Session (Session.flush) to bound the instruction in a single db transaction. In other word do not confuse Hibernate Session with DB session, nevertheless do not confue hibernate Sessio with db connection. Most important is that by specificatio hibernate generate sql code only for what is included between a hibernate transaction. That's why pattern A and B doesn't work and doesn't generate sql code. More specifically the auto-commit in pattern B has no influence since the sql cod is never generated. Moreover, according with hibernate best pracitces, you have to remember to open and close a transaction even for simple select instruction. By the way a select should work even without transaction, but you may have some trouble.

To better understand the concept we can resume the architecture:

  • hibernate session: is a container, wich hold your hibernate object and your db operations as java objects, and many other things. the hibernate transaction: is a transaction object referred to an hibernate session.
  • db connection: is your connection to DB
  • conenction pool: is a set ofdb connection.

What appen when a session is flushed can be resumed with the followoing step:

  1. a connection is get from the connection pool
  2. for each committed transaction in your session a db connection is get from the pool, the sql commands are generated and sent to DB
  3. the db connection is put back on the pool

it is just a small recap, but hope this help r.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download