是否可以在一个Sping Boot 应用程序中同时使用Spring Data R2DBC和Spring Data JPA?

vybvopom  于 12个月前  发布在  Spring
关注(0)|答案(3)|浏览(184)

我有一个应用程序使用Spring data JPA和Hibernate envers进行数据库审计。由于R2DBC还不支持审计,是否可以在单个应用程序中组合使用两者?
如果是,计划是使用Spring Data JPA进行插入,更新和删除操作,以便所有DB审计将由Hibernate Envers处理。并使用R2DBC进行React式非阻塞API读取数据。
如果没有,有没有关于如何实现React式API和审计的建议?

bjg7j2ky

bjg7j2ky1#

  1. Spring通过@EnableR2dbcAuditingcheck my example提供了简单的审计。
    1.在React式应用程序中混合JPA也是可能的,我有an example来演示在React式应用程序中运行JPA,但没有添加r2 dbc。
  • 对于你的计划,一个更好的解决方案是在数据库拓扑上应用cqrs模式,为你的应用程序使用数据库集群。
  • JPA应用更改,使用主/主数据库接受修改,并将更改同步到辅助/从属数据库。
  • r2 dbc对于查询如你所料,使用辅助/从数据库进行查询。
  • 在前端使用网关进行查询和命令服务。
    更新:我已经创建了一个示例来演示JPA and R2dbc coexistence in a single webflux application。但我不建议在实际应用中使用它。如果你真的需要它,请考虑上面的第三个解决方案。
gg58donl

gg58donl2#

是的,这是可能的,但是你可能会面临两个问题,一个是多个repos模块处理需要明确(例如指定相应模块的路径)。
其次,JDBC/JPA Sping Boot 自动配置将被禁用,您需要将其重新导入。这些问题已在Reactive and Non Reactive repository in a Spring Boot application with H2 database中报告,并且可以在此问题中找到解决方案和思考过程:https://github.com/spring-projects/spring-boot/issues/28025

wrrgggsh

wrrgggsh3#

**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());
    }
}

字符串

相关问题