在mose项目中,通过架构验证运行java app
的方式就是使用该配置(使用spring时):
spring.jpa.hibernate.ddl-auto=validate
我遇到了一个问题,我需要在运行过程中的特定时间验证我的模式,有什么方法可以实现它?
我看到休眠状态是通过AbstractSchemaValidator
进行管理的,
我使用的是Spring和Hibernate,但没有找到任何信息来处理它,
我发现的唯一内容是How to validate database schema programmatically in hibernate with annotations?
,但在{{1 }}
spring-boot
有什么想法吗?
答案 0 :(得分:2)
这是解决方案,如果您的用例需要:
如果以上满足您的需求,那么这是如何执行计划的模式验证的示例:
@SpringBootApplication
@EnableScheduling
@EnableConfigurationProperties(ScheamValidatorProperties.class)
public class SchemaValidatorApplication {
public static void main(String[] args) {
SpringApplication.run(SchemaValidatorApplication.class, args);
}
}
@ConfigurationProperties("schema-validator")
class ScheamValidatorProperties {
public Map<String, String> settings = new HashMap<>();
public ScheamValidatorProperties() {
}
public Map<String, String> getSettings() {
return this.settings;
}
public void setSome(Map<String, String> settings) {
this.settings = settings;
}
}
@Component
class ScheduledSchemaValidator {
private ScheamValidatorProperties props;
public ScheduledSchemaValidator(ScheamValidatorProperties props) {
this.props = props;
}
@Scheduled(cron = "0 0/1 * * * ?")
public void validateSchema() {
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(props.getSettings())
.build();
Metadata metadata = new MetadataSources(serviceRegistry)
.addAnnotatedClass(Entity1.class)
.addAnnotatedClass(Entity2.class)
.buildMetadata();
try {
new SchemaValidator().validate(metadata, serviceRegistry);
} catch (Exception e) {
System.out.println("Validation failed: " + e.getMessage());
} finally {
StandardServiceRegistryBuilder.destroy(serviceRegistry);
}
}
}
@Entity
@Table(name = "table1")
class Entity1 {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Entity1() {}
public Long getId() {
return id;
}
}
@Entity
@Table(name = "table2")
class Entity2 {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Entity2() {}
public Long getId() {
return id;
}
}
CREATE DATABASE IF NOT EXISTS testdb;
CREATE TABLE IF NOT EXISTS `table1` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `table2` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
spring:
cache:
type: none
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3309/testdb?useSSL=false&nullNamePatternMatchesAll=true&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: test_user
password: test_password
testWhileIdle: true
validationQuery: SELECT 1
jpa:
show-sql: false
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: none
naming:
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
properties:
hibernate.dialect: org.hibernate.dialect.MySQL8Dialect
hibernate.cache.use_second_level_cache: false
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: false
hibernate.hbm2ddl.auto: validate
schema-validator:
settings:
connection.driver_class: com.mysql.cj.jdbc.Driver
hibernate.dialect: org.hibernate.dialect.MySQL8Dialect
hibernate.connection.url: jdbc:mysql://localhost:3309/testdb?autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
hibernate.connection.username: test_user
hibernate.connection.password: test_password
hibernate.default_schema: testdb
version: '3.0'
services:
db:
image: mysql:8.0.14
restart: always
ports:
- 3309:3306
environment:
MYSQL_ROOT_PASSWORD: test_password
MYSQL_DATABASE: testdb
MYSQL_USER: test_user
MYSQL_PASSWORD: test_password
答案 1 :(得分:2)
如果要让1280
重用项目中已经配置的连接配置和映射信息,而不是再次定义它们以进行模式验证,则应考虑我的解决方案,使您处于DRY状态无需在两个不同的地方维护这些配置。
实际上,SchemaValidator
所需要的是SchemaValidator
实例,该实例仅在引导Hibernate期间可用。但是我们可以使用Hibernate Integrator API(如here中所述)捕获它,以便稍后进行验证。
(1)创建实现Hibernate Integrator API的Metadata
来捕获SchemaValidateService
。还要设置一个Metadata
方法来在所需的时间验证架构。
@Scheduled
(2)注册@Component
public class SchemaValidateService implements Integrator {
private Metadata metadata;
@Override
public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
this.metadata = metadata;
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
}
//Adjust the scheduled time here
@Scheduled(cron = "0 0/1 * * * ?")
public void validate() {
try {
System.out.println("Start validating schema");
new SchemaValidator().validate(metadata);
} catch (Exception e) {
//log the validation error here.
}
System.out.println("Finish validating schema....");
}
}
进入休眠状态
SchemaValidateService
此外,此解决方案应具有更好的性能,因为它无需每次都创建新的数据库连接来验证架构,因为它只需从现有连接池中获取连接即可。