You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot JPA中H2与PostgreSQL持久化行为不一致问题排查

问题:H2与PostgreSQL在Spring Boot JPA下的持久化行为不一致

在测试中使用内存H2数据库时,发现其与PostgreSQL在Spring Boot JPA下的持久化行为不一致:新增实体时,两种数据库都会为实体分配ID,但H2中查询不到新增的条目。希望让两者的持久化行为保持一致,并找出问题所在。

测试代码

System.out.println("BEFORE:");
List<FirstTable> values = myDAO.findAll(FirstTable.class);
values.forEach(System.out::println);

FirstTable ft = new FirstTable();
ft.setValue("added value");
myDAO.save(ft);

System.out.println("AFTER SAVE:");
System.out.println(ft);

System.out.println("TABLE RESULT");
List<FirstTable> values2 = myDAO.findAll(FirstTable.class);
values2.forEach(System.out::println);

数据库输出对比

PostgreSQL输出

pg
BEFORE:
id: 1; value: 1234
id: 2; value: 2345
id: 3; value: 3456
id: 4; value: 4567
AFTER SAVE:
id: 5; value: added value
TABLE RESULT:
id: 1; value: 1234
id: 2; value: 2345
id: 3; value: 3456
id: 4; value: 4567
id: 5; value: added value

H2输出

h2
BEFORE:
id: 1; value: 1234_test
id: 2; value: 2345_test
id: 3; value: 3456_test
id: 4; value: 4567_test
AFTER SAVE:
id: 5; value: added value
TABLE RESULT:
id: 1; value: 1234_test
id: 2; value: 2345_test
id: 3; value: 3456_test
id: 4; value: 4567_test

H2配置

spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test;INIT=runscript from '../src/main/resources/my_dump.sql'
spring.datasource.user=sa
spring.datasource.password=

hibernate.dialect=org.hibernate.dialect.H2Dialect
#spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

MyDaoImpl的save实现

public void save(MyEntity entity) {
    entityManager.persist(entity);
}

完整测试输出

> Task :common:compileJava
> Task :app:compileJava UP-TO-DATE
> Task :app:processResources UP-TO-DATE
> Task :app:classes UP-TO-DATE
> Task :app:compileTestJava UP-TO-DATE
> Task :app:processTestResources
> Task :app:testClasses
> Task :common:processResources NO-SOURCE
> Task :common:classes
> Task :common:jar UP-TO-DATE
2024-01-12T11:57:24.032+03:00  INFO 151062 --- [    Test worker] WorkersTest                              : Starting WorkersTest using Java 17.0.9 with PID 151062 (started by ilys in /home/ilys/Programming/learn/testHibernate/app)
2024-01-12T11:57:24.035+03:00  INFO 151062 --- [    Test worker] WorkersTest                              : No active profile set, falling back to 1 default profile: "default"
2024-01-12T11:57:24.255+03:00  INFO 151062 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2024-01-12T11:57:24.270+03:00  WARN 151062 --- [    Test worker] o.s.b.a.AutoConfigurationPackages        : @EnableAutoConfiguration was declared on a class in the default package. Automatic @Repository and @Entity scanning is not enabled.
2024-01-12T11:57:24.271+03:00  INFO 151062 --- [    Test worker] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 JPA repository interfaces.
2024-01-12T11:57:24.446+03:00  INFO 151062 --- [    Test worker] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2024-01-12T11:57:24.472+03:00  INFO 151062 --- [    Test worker] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 6.3.1.Final
2024-01-12T11:57:24.489+03:00  INFO 151062 --- [    Test worker] o.h.c.internal.RegionFactoryInitiator    : HHH000026: Second-level cache disabled
2024-01-12T11:57:24.592+03:00  INFO 151062 --- [    Test worker] o.s.o.j.p.SpringPersistenceUnitInfo      : No LoadTimeWeaver setup: ignoring JPA class transformer
2024-01-12T11:57:25.037+03:00  INFO 151062 --- [    Test worker] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2024-01-12T11:57:25.058+03:00  INFO 151062 --- [    Test worker] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2024-01-12T11:57:25.357+03:00  INFO 151062 --- [    Test worker] WorkersTest                              : Started WorkersTest in 1.459 seconds (process running for 1.915)
BEFORE:
id: 1; value: 1234_test
id: 2; value: 2345_test
id: 3; value: 3456_test
id: 4; value: 4567_test
AFTER SAVE:
id: 5; value: added value
TABLE RESULT
id: 1; value: 1234_test
id: 2; value: 2345_test
id: 3; value: 3456_test
id: 4; value: 4567_test
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2024-01-12T11:57:25.837+03:00  INFO 151062 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
> Task :app:test
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
BUILD SUCCESSFUL in 3s
7 actionable tasks: 3 executed, 4 up-to-date
11:57:25: Execution finished ':app:test --tests "WorkersTest.sometest"'.

问题原因与解决方案

核心原因:事务与缓存未刷写

Hibernate的persist操作默认仅将实体加入EntityManager的一级缓存,不会立即刷写到数据库。PostgreSQL因事务特性或自动提交机制的差异,能在查询时读取到缓存中的变更;但H2在无事务上下文时,缓存变更不会同步到数据库,导致后续查询看不到新增条目。

具体解决方法

  1. 给测试方法添加事务注解
    在测试方法上加上@Transactional,Spring会自动管理事务上下文,确保persist的变更在当前会话中生效:
@Test
@Transactional
public void sometest() {
    // 测试代码逻辑
}

如果需要测试结束后保留数据,可额外添加@Rollback(false),但一般测试用例无需保留数据。

  1. 手动刷写数据库缓存
    在DAO的save方法中,调用entityManager.flush()强制将缓存中的变更刷写到H2数据库:
public void save(MyEntity entity) {
    entityManager.persist(entity);
    entityManager.flush(); // 强制同步到数据库
}
  1. 优化H2数据库URL配置
    在H2的URL中添加DB_CLOSE_DELAY=-1,防止连接关闭后内存数据库被销毁,确保测试过程中数据库实例始终存在:
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;INIT=runscript from '../src/main/resources/my_dump.sql'
  1. 修复实体扫描警告
    日志中提示"@EnableAutoConfiguration was declared on a class in the default package",将Spring Boot启动类从默认包移到具体包(如com.example.demo),确保Spring能自动扫描@Entity和@Repository,避免潜在的映射问题。

内容的提问来源于stack exchange,提问作者mamol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:59:51