Spring Data JPA测试中使用H2嵌入式数据库提示数据库为空(表不存在)的问题排查求助
Spring Data JPA测试中使用H2嵌入式数据库提示数据库为空(表不存在)的问题排查求助
我最近在学习给Spring Boot应用写数据层测试,想用H2嵌入式数据库来跑ConocimientoRepository的测试,但每次运行测试都会抛出异常,说H2数据库是空的(目标表不存在)。翻了好几个相关的问题尝试解决,都没搞定,只好来这儿求助各位大佬了!
待测试的Repository方法
我要测试的是这个自定义的删除方法,虽然知道这个测试看起来有点多余,但主要是想练手掌握测试的写法:
public interface ConocimientoRepository extends JpaRepository<Conocimiento,Long>{ @Modifying @Transactional @Query(value = "DELETE FROM conocimiento WHERE busca_id = :buscaId", nativeQuery = true) void deleteAllConocimientoFromBuscaId(@Param("buscaId") Long buscaId); }
测试类代码
我的测试类是这样写的,用了@DataJpaTest、指定了H2数据库,还激活了test配置文件:
@DataJpaTest @AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2) @ActiveProfiles("test") public class ConocimientoRepositoryTests { @Autowired BuscaRepository buscaRepository; @Autowired ConocimientoRepository conocimientoRepository; private Busca b1, b2; private List<Conocimiento> listConocimientos; @BeforeEach public void initData() { b1 = new Busca("Ana", "ana@mail.com", "Sevilla", "612345678", "Password1!"); b2 = new Busca("Luis", "luis@mail.com", "Madrid", "712345678", "SecurePwd2@"); listConocimientos = List.of( Conocimiento.builder() .centroEducativo("Centro 1") .titulo("Título 1") .inicioPeriodoConocimiento(LocalDate.of(2020, 1, 1)) .finPeriodoConocimiento(LocalDate.of(2021, 1, 1)) .busca(b1) .build(), Conocimiento.builder() .centroEducativo("Centro 2") .titulo("Título 2") .inicioPeriodoConocimiento(LocalDate.of(2019, 1, 1)) .finPeriodoConocimiento(LocalDate.of(2020, 1, 1)) .busca(b1) .build(), Conocimiento.builder() .centroEducativo("Centro 3") .titulo("Título 3") .inicioPeriodoConocimiento(LocalDate.of(2018, 1, 1)) .finPeriodoConocimiento(LocalDate.of(2019, 1, 1)) .busca(b2) .build() ); b1.setListaConocimientos(listConocimientos.subList(0, 1)); b2.setListaConocimientos(List.of(listConocimientos.get(2))); buscaRepository.saveAll(List.of(b1,b2)); } @Test public void ConocimientoRepository_DeleteAllConocimientoFromBuscaId_RemoveAllConocimientoFromBuscaId() { buscaRepository.delete(b1); Assertions.assertThat(listConocimientos.stream().allMatch(con -> con.getBusca().getId() != b1.getId())); } }
涉及的实体类
Conocimiento实体
@EqualsAndHashCode(of = "id") @Data @ToString(exclude = "busca") @Builder @NoArgsConstructor @AllArgsConstructor @Entity public class Conocimiento { @GeneratedValue(strategy = GenerationType.AUTO) @Id private Long id; @NotNull @Size(max = 40, message = "Máximo 40 carácteres") private String centroEducativo; @NotNull @Size(max = 40, message = "Máximo 40 carácteres") private String titulo; @NotNull private LocalDate inicioPeriodoConocimiento; @NotNull private LocalDate finPeriodoConocimiento; @ManyToOne @JoinColumn(name = "busca_id") @JsonBackReference(value = "busca-conocimiento") private Busca busca; public Conocimiento(@NotNull @Size(max = 40, message = "Máximo 40 carácteres") String centroEducativo, @NotNull @Size(max = 40, message = "Máximo 40 carácteres") String titulo, LocalDate fechaInicio, LocalDate fechaFin) { this.centroEducativo = centroEducativo; this.titulo = titulo; this.inicioPeriodoConocimiento = fechaInicio; this.finPeriodoConocimiento = fechaFin; } }
Busca实体
它继承了Usuario类:
@Data @ToString(exclude = {"listaOfertas"}) @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(of = "id") @Builder @Entity @Table(name = "Busca") public class Busca extends Usuario { @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "busca") private List<Experiencia> listaExperiencias; @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "busca") private List<Conocimiento> listaConocimientos; @JsonBackReference("busca-oferta") @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinTable(name = "busca_oferta", joinColumns = @JoinColumn(name = "busca_id"), inverseJoinColumns = @JoinColumn(name = "oferta_id")) @JsonIgnoreProperties("busca_id") private List<Oferta> listaOfertas; public Busca(String nombre, String email, String ciudad, String telefono, String password) { super(nombre, email, ciudad, telefono, password, Rol.BUSCA); } }
测试环境配置(application-test.properties)
spring.h2.console.enabled=true spring.sql.init.platform=h2 spring.jpa.defer-datasource-initialization=true spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.hibernate.ddl-auto=create-drop
抛出的错误信息
每次运行测试都会报这个错误,核心提示是数据库为空、目标表不存在:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement [Table "
(注:错误栈没复制完整,核心异常就是表找不到)
希望各位大佬能帮我看看问题出在哪儿,谢谢大家了!
内容来源于stack exchange




