![](/img/trans.png)
[英]How to access the original Entity used when repository.save(entity) is invoked from Hibernate AbstractEvents and EventListeners?
[英]Hibernate Validator not triggered as Spring Repository.save() is invoked in unit tests
这是我的实体:
@Builder
@Data
@Entity
@Table(name = "audit_log")
public class AuditEventEntity {
@Id
@GeneratedValue
private UUID id;
private long createdEpoch;
@NotNull
@Size(min = 1, max = 128)
private String label;
@NotNull
@Size(min = 1)
private String description;
}
这是我的存储库:
@Repository
public interface AuditEventRepository extends PagingAndSortingRepository<AuditEventEntity, UUID> {
}
当我为存储库编写以下单元测试时,即使“label”字段为null,保存也会成功!
@DataJpaTest
@RunWith(SpringRunner.class)
public class AuditRepositoryTest {
@Test
public void shouldHaveLabel() {
AuditEventEntity entity = AuditEventEntity.builder()
.createdEpoch(Instant.now().toEpochMilli())
.description(RandomStringUtils.random(1000))
.build();
assertThat(entity.getLabel()).isNullOrEmpty();
AuditEventEntity saved = repository.save(entity);
// Entity saved and didn't get validated!
assertThat(saved.getLabel()).isNotNull();
// The label field is still null, and the entity did persist.
}
@Autowired
private AuditEventRepository repository;
}
无论我使用@NotNull
还是@Column(nullable = false)
,都会在列上使用not null
标志创建数据库:
Hibernate: create table audit_log (id binary not null, created_epoch bigint not null, description varchar(255) not null, label varchar(128) not null, primary key (id))
我认为验证器会自动运行。 我在这做错了什么?
我认为验证器会自动运行。 我在这做错了什么?
您保存实体但不刷新当前实体管理器的状态。
因此,尚未执行实体的验证。
您可以参考Hibernate验证器FAQ :
为什么在调用persist()时我的JPA实体未经过验证?
为什么在调用
persist()
时我的JPA实体未经过验证? 如果您希望触发验证,简短的答案是调用EntityManager#flush()
。Hibernate ORM和其他一些ORM尝试在访问数据库时批量尽可能多的操作。 实际的实体“持久化”操作可能只在您调用
flush()
或事务提交时发生。此外,了解哪个实体将被持久化取决于您的级联策略和对象图的状态。 刷新是指Hibernate ORM识别出已更改并需要数据库操作的所有实体(另请参阅HHH-8028)。
因此,使用JpaRepository.saveAndFlush()
而不是JpaRepository.save()
来允许实体进行验证。
或者,在测试类中注入EntityManager
或TestEntityManager
,调用JpaRepository.save()
,然后调用EntityManager/TestEntityManager.flush()
。
有关信息:
JpaRepository.save()
调用em.persist(entity)
/ em.merge(entity)
JpaRepository.saveAndFlush()
调用JpaRepository.save()
然后调用em.flush()
为了能够调用saveAndFlush()
,您必须使您的Repository接口扩展JpaRepository
例如:
public interface AuditEventRepository extends JpaRepository<AuditEventEntity, UUID> {
由于JpaRepository
扩展了PagingAndSortingRepository
,因此此更改与您现有的声明保持一致。
我想补充一点,这个断言不是必需的:
assertThat(saved.getLabel()).isNotNull();
你要断言的是抛出ValidationException
,也许它包含实际的错误消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.