Hibernate 文档显示了以下示例:
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()即使仅打印了事件列表,为什么仍需要执行?
session.getTransaction().commit()
SELECT还需要事务。没有任何事务就无法执行SELECT。使用某些SQL GUI工具从数据库中选择数据时,不必显式启动和结束事务,这是因为这些工具正在使用自动提交模式。在自动提交模式下,数据库将为每个SQL语句自动启动并提交事务,这样您就不必显式声明事务边界。
如果您不结束(即提交或回滚)事务,则该事务使用的数据库连接将不会被释放,并且您的数据库最终将耗尽可用的连接。
对于hibernate模式,默认情况下使用非自动提交模式(由属性指定hibernate.connection.autocommit)。因此,我们必须声明交易边界并确保交易结束。
hibernate.connection.autocommit
但是,如果仅使用hibernate API查询数据,即使没有显式声明事务边界,也可以这样做,原因如下:
当当前SQL语句需要一个新的事务并且之前没有显式启动任何事务时,数据库通常会自动启动一个新事务。
Session.close()将关闭底层的Connection。根据JDBC规范,如果调用java.sql.Connection#close()并且有一个活动事务,则此活动事务的结果取决于JDBC供应商的实现。通常,JDBC驱动程序会自动提交或回滚此事务。但是在这种情况下,事务是提交还是回滚并不重要,因为您已经获得了所需的数据。
Session.close()