【问题标题】:when using miltiple datasource hibernate envers are not working当使用多个数据源时,休眠环境不起作用
【发布时间】:2018-07-22 11:21:01
【问题描述】:

当我只使用一个数据源时,休眠环境运行良好(不使用任何 config.java。只需设置 application.properties)。但是使用多个数据源(使用 config.java,相同的数据库,不同的用户),envers 无法正常工作并记录 oracle 错误消息 ORA-00942。 审计表在 DB#1 中。我该怎么办?

弹簧靴 1.5.6

application.properties

#################################
#   DataBase #1 (Default)
#################################
spring.datasource.initialize=true
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=id_1
spring.datasource.password=pw_1
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver

#################################
#   DataBase #2(Additional)
#################################
db2.datasource.initialize=true
db2.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
db2.datasource.username=db_2
db2.datasource.password=pw_2
db2.datasource.driverClassName=oracle.jdbc.driver.OracleDriver

config.java

package com.dev;

import javax.sql.DataSource;

import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class DataBaseConfig {

    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource defaultDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean(name = "defaultEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {


        return builder.dataSource(defaultDataSource())
                .packages("com.dev.core.**", "com.dev.ext.**")
                .build();
    }

    @Primary
    @Bean(name = "defaultTransactionManager")
    PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactory(builder).getObject());
    }

    @Configuration
    @EnableJpaRepositories(basePackages= {"com.dev.core.**", "com.dev.ext.**"},
            entityManagerFactoryRef = "defaultEntityManagerFactory", transactionManagerRef = "defaultTransactionManager")
    static class DefaultJpaRepositoriesConfig {
    }

    /*Additional Data Source - NCRM*/
    @Bean
    @ConfigurationProperties(prefix = "db2.datasource")
    public DataSource ncrmDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "ncrmEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean ncrmEntityManagerFactory(EntityManagerFactoryBuilder builder) {

        return builder.dataSource(ncrmDataSource())
                .packages("com.dev.ext.ncrm.*.domain")
                .build();
    }

    @Bean(name = "ncrmTtransactionManager")
    PlatformTransactionManager ncrmTransactionManagerMain(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(ncrmEntityManagerFactory(builder).getObject());
    }

    @Configuration
    @EnableJpaRepositories(
            basePackages="com.dev.ext.ncrm.*.repo",
            entityManagerFactoryRef = "ncrmEntityManagerFactory",
            transactionManagerRef = "ncrmTtransactionManager")
    static class ncrmJpaRepositoriesConfig {
    }
}

defaultDO.java

package com.dev.core.domain;

import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.ColumnResult;
import javax.persistence.ConstructorResult;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.Table;

import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;

import lombok.Data;

@Data
@Entity
@Table(name = "tb_category")
@Audited
@AuditTable("tx_category_audit")
public class CategoryDO {

    //codes 

}

【问题讨论】:

    标签: spring hibernate spring-boot datasource hibernate-envers


    【解决方案1】:

    用户db_2 / pw_2 是否具有访问数据库所需的权限?

    【讨论】:

    • 我认为他们有。因为 db_1 & db_2 是相同的数据库但不同的用户。我可以读取 db_1 和 db_2 的数据。但是只有 db_1 中的审计表数据没有被加载。(400 错误 + ORA-00942)。检查/设置所需权限的方法是什么?
    • 您正尝试使用不同的凭据(id_1 / pw_1 和 db_2 / pw_2)登录到同一个数据库。例如,尝试使用 SQL Developer 客户端登录,同时使用两个帐户并尝试从其中一个审计表中进行选择。
    • 我尝试连接两个用户并选择审计表。(db_1 : select * from db_2.table/db_2 : select * from db_1.audit_table) 在 SQL Developer 中,该查询有效。我可以考虑哪些其他设置?
    • 你没有从同一个表中选择:select * from db_2.table / select * from db_1.audit_table
    • [db_1 : audit_tbl // db_2 : tbl] [登录 db_1] - select * from db_1.audit_tbl / select * from db_2.tbl [logging in db_2] - select * from db_1.audit_tbl / select * from db_2.tbl 我测试过并且都可以工作......
    【解决方案2】:

    首先在 application.properties 文件中为两个数据源添加休眠方言,如下所示:

    spring.datasource.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
    spring.secondDatasource.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
    

    那么请改写如下配置

    package com.multisource.poc.config;
    
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    
    import javax.sql.DataSource;
    import java.util.Properties;
    
    @Configuration
    public class ApplicationConfiguration {
    
        @Value("${spring.datasource.hibernate.dialect}")
        private String oracleDialect;
    
        @Value("${spring.secondDatasource.hibernate.dialect}")
        private String postgresDialect;
    
        @Primary
        @Bean(name = "oracleDB")
        @ConfigurationProperties(prefix = "spring.datasource")
        public DataSource oracleDataSource() {
            return  DataSourceBuilder.create().build();
        }
    
        @Primary
        @Bean(name = "oracleEM")
        public LocalContainerEntityManagerFactoryBean oracleEntityManagerFactory(
                EntityManagerFactoryBuilder builder) {
    
            Properties properties = new Properties();
            properties.setProperty("hibernate.dialect", oracleDialect);
    
            LocalContainerEntityManagerFactoryBean emf = builder
                    .dataSource(oracleDataSource())
                    .packages("entitypackageOne")
                    .persistenceUnit("oraclePU")
                    .build();
    
            emf.setJpaProperties(properties);
    
            return emf;
    
        }
    
    
        @Bean(name = "postgresDB")
        @ConfigurationProperties(prefix = "spring.secondDatasource")
        public DataSource postgresDataSource() {
            return  DataSourceBuilder.create().build();
        }
    
        @Bean(name = "postgresEM")
        public LocalContainerEntityManagerFactoryBean postgresEntityManagerFactory(
                EntityManagerFactoryBuilder builder) {
            Properties properties = new Properties();
            properties.setProperty("hibernate.dialect", postgresDialect);
    
            LocalContainerEntityManagerFactoryBean emf = builder
                    .dataSource(postgresDataSource())
                    .packages("entitypackageTwo")
                    .persistenceUnit("postgresPU")
                    .build();
    
            emf.setJpaProperties(properties);
    
            return emf;
        }
    
    
    }
    

    现在您可以使用两个不同的 EntityManager。样本就像

    @Repository
    public class OracleDao implements InterOracle {
    
        private EntityManager entityManager;
    
        @Autowired
        public OracleDao(@Qualifier("oracleEM") EntityManager entityManager) {
            this.entityManager = entityManager;
        }
    
    }
    
    
    @Repository
    public class PostgresDao implements InterPostGres{
        private static final Logger LOG
                = LoggerFactory.getLogger(PostgresDao.class);
    
    
        private EntityManager entityManager;
    
        @Autowired
        public PostgresDao(@Qualifier("postgresEM") EntityManager entityManager) {
            this.entityManager = entityManager;
        }
    
    }
    

    这就是我的应用程序使用两个不同数据源的工作方式。

    【讨论】:

    • 感谢您的回答!但它也不起作用。首先,当我删除 config.java 中的 DefaultJpaRepositoriesConfig() 和 ncrmJpaRepositoriesConfig() 方法时,会出现类似 [Duplicate '@ConfigurationProperties` definition for prefix 'db2.datasource' 的错误。] 其次,像第一个一样删除,会出现类似 [Field com.dev.ext.audits.repo.CatAuditRepo 中的 catRepo 需要一个名为“entityManagerFactory”的 bean,但无法找到。].
    • 这似乎没有回答问题。
    猜你喜欢
    • 1970-01-01
    • 2013-10-13
    • 2011-11-02
    • 1970-01-01
    • 2011-08-16
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多