gpt4 book ai didi

Spring+Hibernate+SQLite 事务异常

转载 作者:行者123 更新时间:2023-12-03 14:53:02 25 4
gpt4 key购买 nike

我在 Spring + Hibernate + SQLite 堆栈中回滚失败的事务时遇到问题。

这是我的示例的主要类(class)

  • 注释应用配置 http://pastebin.com/XbejGHft
  • 测试 bean http://pastebin.com/3BSFy34p
  • 订购 实体 - 具有两个字段(id 和名称)的 POJO

  • 查看方法 TestBean.testMethod()
    public void testMethod()    {
    entityManager.persist(createOrder("1"));
    entityManager.persist(createOrder("2"));
    entityManager.persist(createOrder("3"));
    entityManager.createQuery("from Order").getResultList();
    entityManager.persist(createOrder("4"));
    throw new RuntimeException("Managed");
    }

    它创建并保留了一些 Order 实体。
    在一些创作之间,它从数据库中读取一些数据。
    最后它抛出 RuntimeException 来模拟方法调用期间的失败并强制 Spring 回滚事务。

    执行后,我打开数据库并查看,它完全回滚仅最后创建的实体(createOrder(“4”))和所有其他(名称为“1”、“2”和“3”)仍然存在于数据库中。但是由于 TestBean 被标记为@Transactional,所以它应该删除在一个事务方法 testMethod() 中创建的所有四个实体。

    我尝试了 SQLIte 中的所有 journal_mode,但回滚仍然无效。

    有任何想法吗?

    最佳答案

    很久之后,我找到了问题的真正原因——它是 @GeneratedValue 的策略类型。应用程序中所有实体的注释。

    默认情况下,注解提供的策略是 AUTO ,这意味着 Hibernate 将使用目标数据库中自己的表 (hibernate_sequence) 来生成 ID 值。 Hibernate 在单独的事务中调用查询(从 hibernate_sequence 中选择当前值)——在这一点上我们遇到了问题。

    如果您使用通用多连接数据源,则 Hibernate 会尝试获取新连接,但 SQLite 只能有一个事件连接 - 我们会收到“数据库文件已锁定”错误。
    如果你使用 Spring 的 SingleConnectionDataSource这会阻止连接关闭,然后 Hibernate 将重用现有连接,但会创建新的单独事务。新交易将成功完成,但要求新 ID 的旧交易将失败。

    所以解决方法很简单,只要确定全部 你的实体像这样注释

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    因此,在这种情况下,Hibernate 会将 ID 值的生成委托(delegate)给底层数据库。

    关于Spring+Hibernate+SQLite 事务异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39182682/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com