多个 SessionFactory 配置失败并出现 org.springframework.beans.factory.UnsatisfiedDependencyException 异常
Multiple SessionFactory configuration fails with org.springframework.beans.factory.UnsatisfiedDependencyException Exception
我们的应用程序需要处理多个数据库。我们尝试通过 Hibernate 配置来配置多个数据源,并添加了两个配置,一个用于数据库 1,另一个用于数据库 2。此配置失败并出现以下异常
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DB1TransactionManager' defined in class path resource [org/npcc/ccms/config/db/HibernateConfig4DB1.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.SessionFactory]: : No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: AgrgtrSessionFactory,HRSessionFactory,StageSessionFactory; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 3: DB1SessionFactory,DB2SessionFactory
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
javax.servlet.GenericServlet.init(GenericServlet.java:160)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
root cause
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: DB1SessionFactory,DB2SessionFactory
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:970)
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
javax.servlet.GenericServlet.init(GenericServlet.java:160)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
第一个数据库配置:
@Configuration
@EnableTransactionManagement
@ComponentScan({ "org.npcc.ccms.config" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfig4DB1 {
final static Logger logger = LogManager.getLogger(HibernateConfig4DB1.class);
@Autowired
private Environment environment;
@Bean(name="DB1SessionFactory")
public LocalSessionFactoryBean db1SessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "org.npcc.ccms.model.db1" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(destroyMethod="")
public DataSource dataSource() {
JndiTemplate jndi = new JndiTemplate();
DataSource dataSource = null;
try {
dataSource = (DataSource) jndi.lookup(environment.getRequiredProperty("datasource"));
} catch (NamingException e) {
logger.error("NamingException for java:comp/env/jdbc/ccms_cp1_orcl", e);
}
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
@Bean(name="DB1TransactionManager")
@Autowired
@Qualifier("DB1SessionFactory")
public HibernateTransactionManager db1TransactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
第二个数据库配置:
@Configuration
@EnableTransactionManagement
@ComponentScan({ "org.npcc.ccms.config" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfig4DB2 {
final static Logger logger = LogManager.getLogger(HibernateConfig4DB2.class);
@Autowired
private Environment environment;
@Bean(name="DB2SessionFactory")
public LocalSessionFactoryBean db2SessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "org.npcc.ccms.model.db2" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(destroyMethod="")
public DataSource dataSource() {
JndiTemplate jndi = new JndiTemplate();
DataSource dataSource = null;
try {
dataSource = (DataSource) jndi.lookup(environment.getRequiredProperty("datasource"));
} catch (NamingException e) {
logger.error("NamingException for java:comp/env/jdbc/ccms_cp1_orcl", e);
}
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
@Bean(name="DB2TransactionManager")
@Autowired
@Qualifier("DB2SessionFactory")
public HibernateTransactionManager db2TransactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
那是因为您在配置中定义了 2 个 SessionFactory
,Spring 猜不出应该选择哪一个。
您可以自动装配您的 sessionFactory 并在您的 @Bean
中使用它:
@Autowired
@Qualifier("DB1SessionFactory")
private SessionFactory sessionFactory;
@Bean(name="DB1TransactionManager")
public HibernateTransactionManager db2TransactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(this.sessionFactory);
return txManager;
}
明确选择要使用的 bean。
此外,您应该注意只有一个配置需要保存 @EnableTransactionManagement
,而且您正在对同一个包进行两次组件扫描,这是不必要的。同样,您有 2 个 @PropertySource
具有相同的属性文件,只需要一个。
在你的情况下,我会创建一个 RootHibernateConfig
包含 @Configuration
、@EnableTransactionManagement
、@ComponentScan({ "org.npcc.ccms.config" })
和 @PropertySource(value = { "classpath:application.properties" })
注释 + @Import
HibernateConfig4DB1
和 HibernateConfig4DB2
.
您可以从 transactionManager beans 方法中删除 @Autowired
和 @Qualifier
注释。不要忘记在您的代码中显式使用所需的 transactionManager。
Spring - Is it possible to use multiple transaction managers in the same application?
我遇到了同样的问题。解决方法如下
@Bean(name = "rebootSessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(
new String[]
{
"com.ra.reboot.b.persistence.entity",
"com.ra.reboot.bl.persistence.entity",
"com.ra.reboot.bla.persistence.entity",
"com.ra.reboot.blaBla.persistence.entity"
});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(name="rebootTransactionManager")
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
private Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "true");
hibernateProperties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
hibernateProperties.setProperty("hibernate.cache.use_query_cache", "true");
hibernateProperties.setProperty("org.hibernate.envers.audit_table_prefix", "history");
hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", "_audit");
hibernateProperties.setProperty("hibernate.jdbc.batch_size", "500");
return hibernateProperties;
}
@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
@Bean
public DataSource dataSource() {
Properties jdbcProperties = this.getJdbcPropertise();
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcProperties.getProperty("jdbc.drive.class"));
dataSource.setUrl(jdbcProperties.getProperty("jdbc.database.url"));
dataSource.setUsername(jdbcProperties.getProperty("jdbc.database.username"));
dataSource.setPassword(jdbcProperties.getProperty("jdbc.database.password"));
return dataSource;
}
private Properties getJdbcPropertise() {
InputStream inputStream = RarebootDataSourceConfig.class.getClassLoader().getResourceAsStream("dev.jdbc.properties");
Properties jdbcProperties = new Properties();
try {
jdbcProperties.load(inputStream);
} catch (NullPointerException IOException) {
System.out.println("dev.jdbc.properties not Found");
throw new RuntimeException();
} catch (IOException e) {
System.out.println("dev.jdbc.properties not Found");
throw new RuntimeException();
}
return jdbcProperties;
}
这是配置文件。然后在BaseDao
@Autowired
@Qualifier("rebootSessionFactory")
public SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public Session getSession() {
return this.sessionFactory.getCurrentSession();
}
在我的服务中
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(value = "rebootTransactionManager")
public class ClientLeadInfoService {
...
}
确保您使用的是这个:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
所以我有 2 个配置文件(这里我 post 只有一个示例文件)。我必须告诉我的 BaseDao 我正在使用哪个会话工厂。在我的服务中,我必须告诉我正在使用哪个事务管理器。
这是由于继承而发生的。有 class BaseClass(base class)和 class DerrivedClass(从 BaseClass 扩展)。当我使用 @Autowire 注释时,它给出了一个错误,原因是有 2 个对象,即 Class BaseClass 和 Class DerrivedClass。
我使用 @Resource 注释而不是 @Autowire 如下
@Resource(名字="derrivedClass")
派生Class testObj;
似乎Spring boot 创建的bean 的名称与class 的骆驼字母名称相同。例如如果我的 class 是 TestClass 那么 bean 名称将是 "testClass"
我们的应用程序需要处理多个数据库。我们尝试通过 Hibernate 配置来配置多个数据源,并添加了两个配置,一个用于数据库 1,另一个用于数据库 2。此配置失败并出现以下异常
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DB1TransactionManager' defined in class path resource [org/npcc/ccms/config/db/HibernateConfig4DB1.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.hibernate.SessionFactory]: : No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: AgrgtrSessionFactory,HRSessionFactory,StageSessionFactory; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 3: DB1SessionFactory,DB2SessionFactory
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
javax.servlet.GenericServlet.init(GenericServlet.java:160)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
root cause
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: DB1SessionFactory,DB2SessionFactory
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:970)
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811)
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:302)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:658)
org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:530)
org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:484)
org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
javax.servlet.GenericServlet.init(GenericServlet.java:160)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
第一个数据库配置:
@Configuration
@EnableTransactionManagement
@ComponentScan({ "org.npcc.ccms.config" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfig4DB1 {
final static Logger logger = LogManager.getLogger(HibernateConfig4DB1.class);
@Autowired
private Environment environment;
@Bean(name="DB1SessionFactory")
public LocalSessionFactoryBean db1SessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "org.npcc.ccms.model.db1" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(destroyMethod="")
public DataSource dataSource() {
JndiTemplate jndi = new JndiTemplate();
DataSource dataSource = null;
try {
dataSource = (DataSource) jndi.lookup(environment.getRequiredProperty("datasource"));
} catch (NamingException e) {
logger.error("NamingException for java:comp/env/jdbc/ccms_cp1_orcl", e);
}
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
@Bean(name="DB1TransactionManager")
@Autowired
@Qualifier("DB1SessionFactory")
public HibernateTransactionManager db1TransactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
第二个数据库配置:
@Configuration
@EnableTransactionManagement
@ComponentScan({ "org.npcc.ccms.config" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfig4DB2 {
final static Logger logger = LogManager.getLogger(HibernateConfig4DB2.class);
@Autowired
private Environment environment;
@Bean(name="DB2SessionFactory")
public LocalSessionFactoryBean db2SessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "org.npcc.ccms.model.db2" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(destroyMethod="")
public DataSource dataSource() {
JndiTemplate jndi = new JndiTemplate();
DataSource dataSource = null;
try {
dataSource = (DataSource) jndi.lookup(environment.getRequiredProperty("datasource"));
} catch (NamingException e) {
logger.error("NamingException for java:comp/env/jdbc/ccms_cp1_orcl", e);
}
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
@Bean(name="DB2TransactionManager")
@Autowired
@Qualifier("DB2SessionFactory")
public HibernateTransactionManager db2TransactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
那是因为您在配置中定义了 2 个 SessionFactory
,Spring 猜不出应该选择哪一个。
您可以自动装配您的 sessionFactory 并在您的 @Bean
中使用它:
@Autowired
@Qualifier("DB1SessionFactory")
private SessionFactory sessionFactory;
@Bean(name="DB1TransactionManager")
public HibernateTransactionManager db2TransactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(this.sessionFactory);
return txManager;
}
明确选择要使用的 bean。
此外,您应该注意只有一个配置需要保存 @EnableTransactionManagement
,而且您正在对同一个包进行两次组件扫描,这是不必要的。同样,您有 2 个 @PropertySource
具有相同的属性文件,只需要一个。
在你的情况下,我会创建一个 RootHibernateConfig
包含 @Configuration
、@EnableTransactionManagement
、@ComponentScan({ "org.npcc.ccms.config" })
和 @PropertySource(value = { "classpath:application.properties" })
注释 + @Import
HibernateConfig4DB1
和 HibernateConfig4DB2
.
您可以从 transactionManager beans 方法中删除 @Autowired
和 @Qualifier
注释。不要忘记在您的代码中显式使用所需的 transactionManager。
Spring - Is it possible to use multiple transaction managers in the same application?
我遇到了同样的问题。解决方法如下
@Bean(name = "rebootSessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(
new String[]
{
"com.ra.reboot.b.persistence.entity",
"com.ra.reboot.bl.persistence.entity",
"com.ra.reboot.bla.persistence.entity",
"com.ra.reboot.blaBla.persistence.entity"
});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(name="rebootTransactionManager")
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
private Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "true");
hibernateProperties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
hibernateProperties.setProperty("hibernate.cache.use_query_cache", "true");
hibernateProperties.setProperty("org.hibernate.envers.audit_table_prefix", "history");
hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", "_audit");
hibernateProperties.setProperty("hibernate.jdbc.batch_size", "500");
return hibernateProperties;
}
@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
@Bean
public DataSource dataSource() {
Properties jdbcProperties = this.getJdbcPropertise();
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(jdbcProperties.getProperty("jdbc.drive.class"));
dataSource.setUrl(jdbcProperties.getProperty("jdbc.database.url"));
dataSource.setUsername(jdbcProperties.getProperty("jdbc.database.username"));
dataSource.setPassword(jdbcProperties.getProperty("jdbc.database.password"));
return dataSource;
}
private Properties getJdbcPropertise() {
InputStream inputStream = RarebootDataSourceConfig.class.getClassLoader().getResourceAsStream("dev.jdbc.properties");
Properties jdbcProperties = new Properties();
try {
jdbcProperties.load(inputStream);
} catch (NullPointerException IOException) {
System.out.println("dev.jdbc.properties not Found");
throw new RuntimeException();
} catch (IOException e) {
System.out.println("dev.jdbc.properties not Found");
throw new RuntimeException();
}
return jdbcProperties;
}
这是配置文件。然后在BaseDao
@Autowired
@Qualifier("rebootSessionFactory")
public SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public Session getSession() {
return this.sessionFactory.getCurrentSession();
}
在我的服务中
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(value = "rebootTransactionManager")
public class ClientLeadInfoService {
...
}
确保您使用的是这个:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
所以我有 2 个配置文件(这里我 post 只有一个示例文件)。我必须告诉我的 BaseDao 我正在使用哪个会话工厂。在我的服务中,我必须告诉我正在使用哪个事务管理器。
这是由于继承而发生的。有 class BaseClass(base class)和 class DerrivedClass(从 BaseClass 扩展)。当我使用 @Autowire 注释时,它给出了一个错误,原因是有 2 个对象,即 Class BaseClass 和 Class DerrivedClass。
我使用 @Resource 注释而不是 @Autowire 如下 @Resource(名字="derrivedClass") 派生Class testObj;
似乎Spring boot 创建的bean 的名称与class 的骆驼字母名称相同。例如如果我的 class 是 TestClass 那么 bean 名称将是 "testClass"