当使用多个数据源时,休眠环境不起作用
Posted
技术标签:
【中文标题】当使用多个数据源时,休眠环境不起作用【英文标题】: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
【问题讨论】:
【参考方案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,但无法找到。]. 这似乎没有回答问题。以上是关于当使用多个数据源时,休眠环境不起作用的主要内容,如果未能解决你的问题,请参考以下文章
具有多个条件但 @WhereJoinTable 不起作用的休眠连接表
当 RHS 有多个字符串或字符时,C++11 += 运算符不起作用