8

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()即使只是打印了事件列表,为什么还要执行?

4

1 回答 1

11

SELECT 也需要事务。没有任何事务就不可能执行 SELECT。在使用某些 SQL GUI 工具从 DB 中选择数据时,您不必显式地开始和结束事务,因为这些工具使用的是自动提交模式。在自动提交模式下,数据库将自动启动并提交每个 SQL 语句的事务,这样您就不必显式声明事务边界。

如果您不结束(即提交或回滚)事务,则该事务使用的数据库连接将不会被释放,并且您的数据库最终将耗尽可用连接。

对于休眠,它默认使用非自动提交模式(由属性指定hibernate.connection.autocommit)。所以我们必须声明事务边界并确保事务结束。

但是如果你只使用 hibernate API 查询数据,即使你没有显式声明事务边界也没关系,因为以下原因:

  1. 当当前 SQL 语句需要一个新事务并且之前没有显式启动任何事务时,数据库通常会自动启动一个新事务。

  2. Session.close()close()底层Connection。根据 JDBC 规范,如果调用java.sql.Connection#close()并且存在活动事务,则此活动事务的结果取决于 JDBC 供应商的实现。通常,JDBC 驱动程序会自动提交或回滚这个事务。但是在这种情况下,事务提交还是回滚都没有关系,因为您已经获得了您想要的数据。

于 2013-07-06T21:43:24.857 回答