Hibernate docs显示了这个例子:
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery( "from Event" ).list();
for ( Event event : (List<Event>) result ) {
System.out.println( "Event (" + event.getDate() + ") : " +
event.getTitle() );
}
session.getTransaction().commit();
session.close();
为什么有必要执行session.getTransaction().commit()
,即使事件列表只是打印出来了?
答案 0 :(得分:11)
SELECT也需要交易。没有任何事务就不可能执行SELECT。使用某些SQL GUI工具从DB中选择数据时,您不必显式启动和结束事务,这些工具使用autocommit模式。在自动提交模式下,数据库将自动启动并为每个单个SQL语句提交事务,这样您就不必显式声明事务边界。
如果您没有结束(即提交或回滚)事务,则不会释放此事务使用的数据库连接,并且您的数据库最终将耗尽可用连接。
对于hibernate,它默认使用非自动提交模式(由属性hibernate.connection.autocommit
指定)。所以我们必须声明事务边界并确保事务结束。
但是如果您只使用hibernate API查询数据,即使您没有明确声明事务边界,也可以,因为以下内容:
当前SQL语句需要一个并且以前没有显式启动任何事务时,数据库通常会自动启动一个新事务。
Session.close()
将close()基础Connection。根据JDBC规范,如果调用java.sql.Connection#close()且存在活动事务,则结果为active transaction取决于JDBC供应商的实现。通常,JDBC驱动程序将自动提交或回滚此事务。但在这种情况下,事务提交或回滚无关紧要,因为您已经获得了所需的数据。