【发布时间】:2020-07-21 13:02:45
【问题描述】:
通读这篇文章
有这样的引用“当 Hibernate 或任何其他 JPA 实现触发预持久、预更新或预删除生命周期事件时,验证会自动执行”
所以,我期待失败会持续存在。我添加了 hibernate-validator 但没有添加 el 的东西(没有它似乎不会失败......不知道为什么它需要 el)。
在某处是否有一个运行中的简单 github 示例我可以比较以跟踪此问题?
版本:
- org.hibernate:hibernate-core:5.4.10.Final
- org.hibernate:hibernate-validator:5.4.3.Final
- org.glassfish:javax.el:3.0.1-b09
我只是从 javax.validation.constraints 中添加了一堆这样的注释。并且预计 entityManager.persist 会失败,但它可以工作并将 bean 插入数据库中。
@NotNull
@NotBlank
private String phone;
@NotNull
@NotBlank
private String name;
@NotNull
@NotBlank
private String firstName;
我使用一个类
public class DbSettingsInMemory implements PersistenceUnitInfo
的
public class DbSettingsInProd implements PersistenceUnitInfo
而不是persistence.xml。不确定这是否真的很重要。我们这样做是为了避免在 IDE 等中出现的查找 persistence.xml 的类路径问题,并且这样的体验更加流畅。这是我们的完整文件,以防它无法工作
public class DbSettingsInMemory implements PersistenceUnitInfo {
private static final Logger log = LoggerFactory.getLogger(DbSettingsInMemory.class);
private Properties properties = new Properties();
private HikariDataSource dataSource;
@Inject
public DbSettingsInMemory(MeterRegistry metrics) {
//<!-- property name="javax.persistence.jdbc.driver" value="org.h2.Driver" /-->
//properties.setProperty("javax.persistence.jdbc.driver", "net.sf.log4jdbc.DriverSpy");
//properties.setProperty("javax.persistence.jdbc.url", "jdbc:log4jdbc:h2:mem:test");
//properties.setProperty("javax.persistence.jdbc.user", "sa");
//properties.setProperty("javax.persistence.jdbc.password", "");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.show_sql", "false");
properties.setProperty("hibernate.format_sql", "false");
properties.setProperty("hibernate.transaction.flush_before_completion", "true");
//properties.setProperty("hibernate.connection.provider_class", "org.hibernate.hikaricp.internal.HikariCPConnectionProvider");
HikariConfig config = new HikariConfig();
config.setDriverClassName("net.sf.log4jdbc.DriverSpy");
config.setJdbcUrl("jdbc:log4jdbc:h2:mem:test");
config.setUsername("sa");
config.setPassword("");
config.setMetricRegistry(metrics);
dataSource = new HikariDataSource(config);
}
@Override
public String getPersistenceUnitName() {
return "inmemory";
}
@Override
public String getPersistenceProviderClassName() {
return "org.hibernate.jpa.HibernatePersistenceProvider";
}
@Override
public PersistenceUnitTransactionType getTransactionType() {
return PersistenceUnitTransactionType.RESOURCE_LOCAL;
}
@Override
public DataSource getJtaDataSource() {
return null;
}
@Override
public DataSource getNonJtaDataSource() {
return dataSource;
}
@Override
public List<String> getMappingFileNames() {
return null;
}
@Override
public List<URL> getJarFileUrls() {
return null;
}
/**
* root of where to scan from. MAKE this a very small scope so scanning is very very quick
*/
@Override
public URL getPersistenceUnitRootUrl() {
String name = DbSettingsInMemory.class.getSimpleName() + ".class";
URL url = DbSettingsInMemory.class.getResource(name);
String file = url.getFile();
int length = file.length() - name.length();
String root = file.substring(0, length);
try {
URL rootUrl = new URL(url.getProtocol(), url.getHost(), root);
log.info("RootURL for scanning="+rootUrl);
return rootUrl;
} catch (MalformedURLException e) {
throw new RuntimeException("Bug", e);
}
}
@Override
public List<String> getManagedClassNames() {
return null;
}
@Override
public boolean excludeUnlistedClasses() {
return false;
}
@Override
public SharedCacheMode getSharedCacheMode() {
return SharedCacheMode.ENABLE_SELECTIVE;
}
@Override
public ValidationMode getValidationMode() {
return ValidationMode.NONE;
}
@Override
public Properties getProperties() {
return properties;
}
@Override
public String getPersistenceXMLSchemaVersion() {
return null;
}
@Override
public ClassLoader getClassLoader() {
throw new UnsupportedOperationException("Not supported. webpieces needs to pass in Development Classloader");
}
@Override
public void addTransformer(ClassTransformer transformer) {
}
@Override
public ClassLoader getNewTempClassLoader() {
return null;
}
}
编辑: 我想到了要添加的其他内容,至少要确保验证在像这样调用持久/刷新之前正常工作
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<UserDbo>> list = validator.validate(entity);
log.info("list="+list);
Em.get().persist(entity);
Em.get().flush();
我在列表中正确地看到了 4 个违规行为,但仍然存在并且刷新成功 :(.
从调试器...
深入研究休眠代码,我找到了一个 BeanValidationEventListener.java 但它似乎只是通过依赖注入连接的??不太确定,但由于某种原因它没有连接到休眠,但需要以某种方式休眠。
谢谢, 院长
【问题讨论】:
-
您使用的是 spring-boot,如果是,是什么版本?您声明了哪些与验证相关的依赖项?
-
@KavithakaranKanapathippillai 不,只在应用程序中使用休眠。 'org.hibernate:hibernate-core:5.4.10.Final'、'org.hibernate:hibernate-validator:6.1.5.Final'和'org.glassfish:javax.el:3.0.1-b09',
标签: hibernate hibernate-validator