Java 休眠会话。如果不在事务中,则更新不工作

Java 休眠会话。如果不在事务中,则更新不工作,java,mysql,hibernate,jakarta-ee,transactions,Java,Mysql,Hibernate,Jakarta Ee,Transactions,我的hibernate配置: 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("hi

我的hibernate配置:

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);
代码示例:

// 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();
请忽略我的编译错误。我在web应用程序中使用hibernate(不使用
spring
),也不使用事务,因为我使用的是
MySql
数据库,并且
MySql
自动提交是真的,所以反过来,在hibernate中,我也将其设置为
autocommit
真的。(我也在使用
mysql-connector-java-5.1.23-bin.jar

三个模式,我只能得到模式3的作品。我现在完全糊涂了。我有以下几个问题:

1) 我不明白为什么模式1不起作用,我所有的
选择
(通过hibernate
CriteriaBuilder
加载
)和
插入
(通过hibernate
会话。保存
)都起作用,但只有更新不起作用

2) 好的,然后我尝试使用类似于模式2的事务,我的hibernate
auto commit
是真的,所以我假设当我关闭会话时,事务应该自动提交,但它不工作。为什么?

3) 模式3有效,为什么我需要事务管理器?我希望
jdbc
在每个事务中执行每个查询(在一个事务中执行一个sql),我不担心性能,但我必须在这里包含事务,为什么

对于模式1和模式2,我发现甚至没有生成
update
脚本(基于hibernate日志),问题不是因为生成了脚本,而是提交失败了。不明白为什么?请帮忙


附言:

经过一些尝试和错误后,总结一些要点供将来参考:

1) Hibernate仅在调用
会话时生成sql脚本。flush()
,但不调用
tx.commit()
,并且必须在事务块中调用
session.flush()
。如果没有事务,则会导致异常。如果刷新模式为自动,则不需要显式刷新,
commit()
将触发刷新

2) Hibernate事务并不等同于数据库事务,经过一些尝试后,我发现,如果Hibernate autocommit为false,则是的,它们在功能上是等效的,并且相应的
begin Transaction
脚本通过JDBC生成并发送到数据库(仅限我的猜测)。如果hibernate autocommit为true,则不会启动任何
开始事务
,尽管我们在hibernate
事务tx=s.beginTransaction()
中声明了它,但所有查询都将是自动提交,并且
回滚
将不起作用

3) 在我的案例中,
session.save()
(以及
select
)可以在没有事务的情况下工作,这有点特殊,因为必须触发
save
,才能获得表标识符(主键),因此即使没有刷新也会生成sql脚本

4) 对于模式2,我不理解,autocommit并不意味着会话关闭时自动提交,它的真正含义应该是每次sql到达数据库时自动提交。因此模式2将不起作用,因为没有
tx.commit
,这意味着没有刷新,因此不会生成sql脚本。(是否在
会话关闭时自动调用
tx.commit
,这取决于供应商的实施,有些将回滚。)


总之,在Hibernate中不管发生什么都需要事务块。

我认为您有点困惑。事务(org.hibernate.transaction)并不完全是一个DB事务。 当您刷新会话(Session.flush)以将指令绑定到单个db事务中时,hibernate会使用这样的对象。换句话说,不要混淆Hibernate会话和DB会话,但是不要混淆Hibernate会话和DB连接。 最重要的是,hibernate只为hibernate事务之间包含的内容生成sql代码。这就是为什么模式A和B不工作,也不生成sql代码的原因。更具体地说,模式B中的自动提交没有任何影响,因为从来没有生成过SQLCOD。此外,根据hibernate最佳实践,即使对于简单的select指令,也必须记住打开和关闭事务。顺便说一下,即使没有事务,select也应该可以工作,但是您可能会遇到一些麻烦

为了更好地理解概念,我们可以恢复架构:

  • hibernate session:是一个容器,它将hibernate对象和db操作作为java对象保存,以及其他许多东西。 hibernate事务:是指hibernate会话的事务对象
  • db连接:您是否连接到db
  • 连接池:是一组DB连接
刷新会话时出现的内容可以通过以下步骤恢复:

  • 从连接池中获取连接
  • 每一个承诺 会话中的事务从池中获取db连接, sql命令被生成并发送到DB
  • 数据库连接被放回池中
  • 这只是一个小小的回顾,但希望能有所帮助
    r、

    我猜Hibernate本身没有处于自动提交模式,尽管您已经设置了
    Hibernate.connection.autocommit
    连接字符串。顺便说一句,将Hibernate设置为自动提交模式可能不是一个好主意,因为如果出现问题,它不会回滚任何内容。感谢您的重述,我认为我最好始终遵循模式3,因为我找不到关于Hibernate
    自动提交的好解释,基于我的情况,我不理解为什么我的模式1,
    session.save()
    仍然可以在没有事务的情况下工作……我忘记了,
    autocommit
    与hibernate事务无关,但它用于(不推荐)在每次JDBC调用后释放连接。您可以在这里找到详细信息[我想你提到的是
    hibernate.connection.release\u mode
    。对于自动提交,hibernate只有两行解释,这让我非常困惑: