我有一个使用Spring Data JPA和Hibernate Envers用于数据库审计的应用程序。 由于R2DBC尚不支持审计,是否可以在单个应用程序中同时使用两者的组合?
如果是,计划是使用Spring Data JPA进行插入、更新和删除操作,以便所有的数据库审计都由Hibernate Envers处理。并使用R2DBC来读取数据的响应式非阻塞API。
如果不行,是否有任何建议来实现响应式API和审计?
我有一个使用Spring Data JPA和Hibernate Envers用于数据库审计的应用程序。 由于R2DBC尚不支持审计,是否可以在单个应用程序中同时使用两者的组合?
如果是,计划是使用Spring Data JPA进行插入、更新和删除操作,以便所有的数据库审计都由Hibernate Envers处理。并使用R2DBC来读取数据的响应式非阻塞API。
如果不行,是否有任何建议来实现响应式API和审计?
Spring提供了简单的审计功能,通过 @EnableR2dbcAuditing
实现,在我的示例中查看。
在响应式应用程序中混合使用JPA也是可能的,我有一个示例,演示了如何在响应式应用程序中运行JPA,但其中没有添加r2dbc。
对于您的计划,更好的解决方案是在数据库拓扑结构上应用cqrs模式,为您的应用程序使用数据库集群。
更新: 我创建了一个示例,演示了如何在单个webflux应用程序中同时使用JPA和R2dbc,可以在这里查看。但我不建议在实际应用中使用它,请考虑上述第3种解决方案。
**Here are the changes I did :
I am trying to catch a trigger from postgres on updation of the table content.**
**R2dbc Config**
@Configuration
public class R2dbcConfig {
@Value("${spring.r2dbc.url}")
private String url;
@Value("${spring.r2dbc.name}")
private String name;
@Value("${spring.r2dbc.username}")
private String username;
@Value("${spring.r2dbc.password}")
private String password;
@Bean
public ConnectionFactory connectionFactory() {
return new PostgresqlConnectionFactory(
PostgresqlConnectionConfiguration.builder()
.host(url)
.database(name)
.username(username)
.password(password)
.build()
);
}
@Bean
DatabaseClient databaseClient(ConnectionFactory connectionFactory) {
return DatabaseClient.builder()
.connectionFactory(connectionFactory)
.namedParameters(true)
.build();
}
}
**Jpa Config:**
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.artemis.repositories")
@EntityScan("com.artemis.entities")
@Slf4j
public class JpaConfig implements EnvironmentAware {
private static final String ENV_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String ENV_HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
private static final String ENV_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String ENV_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
private Environment env;
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(
env.getProperty("datasource.url"),
env.getProperty("datasource.username"),
env.getProperty("datasource.password")
);
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource);
emf.setPackagesToScan(ArtemisApplication.class.getPackage().getName());
emf.setPersistenceProvider(new HibernatePersistenceProvider());
emf.setJpaProperties(jpaProperties());
return emf;
}
private Properties jpaProperties() {
Properties extraProperties = new Properties();
extraProperties.put(ENV_HIBERNATE_FORMAT_SQL, env.getProperty(ENV_HIBERNATE_FORMAT_SQL));
extraProperties.put(ENV_HIBERNATE_SHOW_SQL, env.getProperty(ENV_HIBERNATE_SHOW_SQL));
extraProperties.put(ENV_HIBERNATE_HBM2DDL_AUTO, env.getProperty(ENV_HIBERNATE_HBM2DDL_AUTO));
if (log.isDebugEnabled()) {
log.debug(" hibernate.dialect @" + env.getProperty(ENV_HIBERNATE_DIALECT));
}
if (env.getProperty(ENV_HIBERNATE_DIALECT) != null) {
extraProperties.put(ENV_HIBERNATE_DIALECT, env.getProperty(ENV_HIBERNATE_DIALECT));
}
return extraProperties;
}
@Bean
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory.getObject());
}
@Override
public void setEnvironment(Environment environment) {
this.env = environment;
}
}
And my service class:
class myService{
final PostgresqlConnection connection;
public myService(ConnectionFactory connectionFactory ) {
this.connection = Mono.from(connectionFactory.create())
.cast(PostgresqlConnection.class).block();
}
@PostConstruct
private void postConstruct() {
connection.createStatement("LISTEN my_channel").execute()
.flatMap(PostgresqlResult::getRowsUpdated).subscribe();
connection.getNotifications().subscribe(myService::catchTrigger);
}
private static void catchTrigger(Notification notification) {
System.out.println(notification.getName());
System.out.println(notification.getParameter());
}
}