Spring 弹簧&x2B;冬眠+;SQLite事务异常

Spring 弹簧&x2B;冬眠+;SQLite事务异常,spring,hibernate,sqlite,jpa,transactions,Spring,Hibernate,Sqlite,Jpa,Transactions,我在Spring+Hibernate+SQLite堆栈中遇到回滚失败事务的问题 下面是我的示例的主要类 注释应用程序配置 TestBean 订单实体-带有两个字段(id和名称)的POJO 查看TestBean.testMethod()方法 它创建并保持一些订单实体。 在一些创建之间,它从数据库中读取一些数据。 最后,它抛出RuntimeException来模拟方法调用期间的失败,并强制Spring回滚事务 执行后,我打开数据库并查看它是否完全回滚最后创建的实体(createOrder(“4”

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

下面是我的示例的主要类

  • 注释应用程序配置
  • TestBean
  • 订单实体-带有两个字段(id和名称)的POJO
查看TestBean.testMethod()方法

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

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

我在SQLIte中尝试了所有日志模式,但回滚仍然不起作用


有什么想法吗?

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

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

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

所以解决方案非常简单,只需确保所有的实体都是这样注释的

@GeneratedValue(strategy = GenerationType.IDENTITY)

因此,在本例中,Hibernate将把ID值的生成委托给底层数据库。

似乎Hibernate在每个em.persist()调用上调用JdbcIsolationDelegate#delegateWork。同时,方法JdbcIsolationDelegate#delegateWork调用Connection#commit,它中断了JPA/Hibernate框架中的所有事务性交互,我似乎被这一点烧坏了,我还试图让Spring Boot与sqlite3一起工作:我一直得到“数据库已锁定”@Transactional注释中出现异常,原因是-我使用的是GenerationType.SEQUENCE,Hibernate尝试管理序列生成,同时创建新实体。我一切换到GenerationType.IDENTITY,它就工作了。
@GeneratedValue(strategy = GenerationType.IDENTITY)