Hibernate JPARepository:deleteAll()上没有发生任何事情;deleteAllInBatch()有效
在我的Spring集成测试中(使用JUnit 5。我的测试类被注释为Hibernate JPARepository:deleteAll()上没有发生任何事情;deleteAllInBatch()有效,hibernate,spring-boot,jpa,spring-data-jpa,junit5,Hibernate,Spring Boot,Jpa,Spring Data Jpa,Junit5,在我的Spring集成测试中(使用JUnit 5。我的测试类被注释为@SpringBootTest(classes={SecurityBeanOverrideConfiguration.class,XXXApp.class}),我试图在每个方法之后调用repository.deleteAll() 查看日志中的SQL,似乎没有执行任何操作;事实上,在接下来的测试中,无法创建具有相同ID的实体,因为它已经存在——这意味着数据库受到了阻碍。正如其他问题所提到的,我使用了不同的事务类型(传播、隔离…),
@SpringBootTest(classes={SecurityBeanOverrideConfiguration.class,XXXApp.class})
,我试图在每个方法之后调用repository.deleteAll()
查看日志中的SQL,似乎没有执行任何操作;事实上,在接下来的测试中,无法创建具有相同ID的实体,因为它已经存在——这意味着数据库受到了阻碍。正如其他问题所提到的,我使用了不同的事务类型(传播、隔离…),但没有用
有趣的是,调用repository.deleteAllInBatch()
而不是deleteAll()
确实有效:所有测试都通过了
发生了什么事
编辑:添加代码
@Transactional
@SpringBootTest(类={SecurityBeanOverrideConfiguration.class,XXXApp.class})
公共类DeviceResourceIT{
@自动连线装置正性装置正性装置;
@自动连线设备服务;
@自连线专用映射Jackson2HttpMessageConverter jacksonMessageConverter;
@自动连线专用例外Translator例外Translator;
私有MockMvc-MockMvc;
私有记录器log=LoggerFactory.getLogger(DeviceResourceIT.class);
@施工后
无效设置(){
DeviceResource DeviceResource=新的DeviceResource(deviceService);
mockMvc=MockMvcBuilders.standaloneSetup(DeviceSource)
.setControllerAdvice(Translator除外)
.setConversionService(createFormattingConversionService())
.SetMessageConverter(jacksonMessageConverter)
.build();
}
@试验
public void getLot()引发异常
{
线状洗液;
字符串d=“aRandomString”;
最终列表请求=Arrays.asList(
新设备请求到(“l1”、“ble1”),
新设备请求到(“l2”、“ble2”),
新设备请求DTO(“l3”、“ble3”)
);
LotDTO LotDTO=新的LotDTO(请求);
MvcResult MvcResult=mockMvc.perform(post(“/api/admin/lot”)
.contentType(MediaType.APPLICATION_JSON)
.字符编码(“utf-8”)
.content(toJsonString(lotDTO)))
.andDo(print())
.andExpect(状态().isOk())
.andReturn();
LotDTO returnedLotDTO=convertJsonBytes(mvcResult.getResponse().getContentAsByteArray(),LotDTO.class);
lotID=returnedLotDTO.getId();
log.info(“{批次id为:}”+lotID);
//检索具有正确批次ID的批次
perform(get(“/api/admin/lot/{lot_id}”,lotID))
.andDo(print())
.andExpect(status().isOk());
}
@之后
公共无效拆卸(){
试一试{
log.info(“{}”,devicepository.count());
//报税表:3
deviceepository.deleteAll();
log.info(“{}”,devicepository.count());
//报税表:3
//…但如果调用
//deleteAll()就在上面。。。
}捕获(例外e){
Fail.Fail(如getMessage());
}
}
}
诊断这是一个奇怪的错误。结果表明,我实现的isNew()
(属于持久化的
)错误,并且返回了true
因此,调用simpleparepository#delete(T entity)
执行以下检查:
public void deleteAll(T实体)
// [...]
if(entityInformation.isNew(实体)){
返回;
}
//实际上删除。。。
// [...]
}
我的实体正在返回isNew()=true
,因此,存储库自然会跳过所有实体,而从不删除它们。同时,deleteAllInBatch()
不会执行该检查
为了解决这个问题,我已经停止实现持久化
,而是将我的实体序列化
2020年6月更新:
无需切换到可序列化的最小实现示例:
类XXX实现了持久化
{
@Id私有字符串Id;
//(getter、setter、logic等)
//为持久化接口实现`T getId()`方法,
//很可能这只是上面id字段的一个getter
//瞬态字段不存储,但向Hibernate/JPA提供信息
//关于此实体实例的状态
@暂时私有布尔值=false;
@PostPersist@PostLoad void setpersistend(){
持续=真;
}
@重写公共布尔值isNew(){
回来!坚持;
}
}
诊断这是一个奇怪的错误。结果表明,我实现的isNew()
(属于持久化的
)错误,并且返回了true
因此,调用simpleparepository#delete(T entity)
执行以下检查:
public void deleteAll(T实体)
// [...]
if(entityInformation.isNew(实体)){
返回;
}
//实际上删除。。。
// [...]
}
我的实体正在返回isNew()=true
,因此,存储库自然会跳过所有实体,而从不删除它们。同时,deleteAllInBatch()
不会执行该检查
为了解决这个问题,我已经停止实现持久化
,而是将我的实体序列化
2020年6月更新:
无需切换到可序列化的最小实现示例:
类XXX实现了持久化
{