首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有多个DataSource的hibernate配置类

具有多个DataSource的hibernate配置类
EN

Stack Overflow用户
提问于 2019-11-30 20:32:04
回答 2查看 852关注 0票数 4

我们的应用程序需要处理多个数据库。我们尝试通过Hibernate配置来配置多个数据源,并添加了两个配置,一个用于数据库1,另一个用于数据库2。

代码语言:javascript
运行
复制
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainController': Unsatisfied dependency expressed through field 'dataDAO'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataDAO': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available: expected single matching bean but found 2: sessionFactory1,sessionFactory2
Nov 29, 2019 5:08:11 PM org.springframework.web.context.ContextLoader initWebApplicationContext
SEVERE: Context initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainController': Unsatisfied dependency expressed through field 'dataDAO'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataDAO': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.hibernate.SessionFactory' available: expected single matching bean but found 2: sessionFactory1,sessionFactory2
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)

这是我的配置类:

代码语言:javascript
运行
复制
package com.pack1.config;

import java.beans.PropertyVetoException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import com.pack1.routing.MyRoutingDataSource;

@Configuration
@ComponentScan("com.pack1")
@EnableWebMvc
@EnableTransactionManagement

// Load to Environment
@PropertySources({@PropertySource("classpath:ds/datasource-cfg.properties")})

public class ApplicationContextConfig implements WebMvcConfigurer
{


    // The Environment class serves as the property holder
    // and stores all the properties loaded by the @PropertySource
    @Autowired
    private Environment env;

    private Logger logger = Logger.getLogger(getClass().getName());

    @Bean(name = "viewResolver")
    public InternalResourceViewResolver getViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

    // Returns Routing DataSource (MyRoutingDataSource)
    @Autowired
    @Bean(name = "dataSource")
    public DataSource getDataSource(DataSource dataSource1, DataSource dataSource2) {

        System.out.println("## Create DataSource from dataSource1 & dataSource2");

        MyRoutingDataSource dataSource = new MyRoutingDataSource();

        Map<Object, Object> dsMap = new HashMap<Object, Object>();
        dsMap.put("PUBLISHER_DS", dataSource1);
        dsMap.put("ADVERTISER_DS", dataSource2);

        dataSource.setTargetDataSources(dsMap);

        return dataSource;
    }

    @Bean(name = "dataSource1")
    public DataSource getDataSource1() throws SQLException, PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        // See: datasouce-cfg.properties
        dataSource.setDriverClass(env.getProperty("ds.database-driver1"));
        dataSource.setJdbcUrl(env.getProperty("ds.url1"));
        dataSource.setUser(env.getProperty("ds.username1"));
        dataSource.setPassword(env.getProperty("ds.password1"));

        System.out.println("## getDataSource1: " + dataSource);

        return dataSource;
    }

    private Properties getHibernateProperties1() 
    {
        // set hibernate properties
        Properties props = new Properties();

        props.setProperty("ds.hibernate.dialect1", env.getProperty("ds.hibernate.dialect1"));
        props.setProperty("ds.hibernate.show_sql1", env.getProperty("ds.hibernate.show_sql1"));

        return props;
    }

 // need a helper method 
    // read environment property and convert to int

    private int getIntProperty1(String propName) {

        String propVal = env.getProperty(propName);

        // now convert to int
        int intPropVal = Integer.parseInt(propVal);

        return intPropVal;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory1() throws SQLException, PropertyVetoException{

        // create session factorys
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();

        // set the properties
        sessionFactory.setDataSource(getDataSource1());
        sessionFactory.setPackagesToScan(env.getProperty("ds.hibernate.packagesToScan1"));
        sessionFactory.setHibernateProperties(getHibernateProperties1());

        return sessionFactory;
    }

    @Autowired
    @Bean(name = "transactionManager")
    public HibernateTransactionManager getTransactionManager1(SessionFactory sessionFactory1) {

        // setup transaction manager based on session factory 
        HibernateTransactionManager txManager = new HibernateTransactionManager();

        txManager.setSessionFactory(sessionFactory1);

        return txManager;
    }


    @Bean(name = "dataSource2")
    public DataSource getDataSource2() throws SQLException, PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        // See: datasouce-cfg.properties
        dataSource.setDriverClass(env.getProperty("ds.database-driver2"));
        dataSource.setJdbcUrl(env.getProperty("ds.url2"));
        dataSource.setUser(env.getProperty("ds.username2"));
        dataSource.setPassword(env.getProperty("ds.password2"));

        System.out.println("## getDataSource2: " + dataSource);

        return dataSource;
    }

    private Properties getHibernateProperties2() 
    {
        // set hibernate properties
        Properties props = new Properties();

        props.setProperty("ds.hibernate.dialect2", env.getProperty("ds.hibernate.dialect2"));
        props.setProperty("ds.hibernate.show_sql2", env.getProperty("ds.hibernate.show_sql2"));

        return props;
    }

 // need a helper method 
    // read environment property and convert to int

    private int getIntProperty2(String propName) {

        String propVal = env.getProperty(propName);

        // now convert to int
        int intPropVal = Integer.parseInt(propVal);

        return intPropVal;
    }


    @Bean
    public LocalSessionFactoryBean sessionFactory2() throws SQLException, PropertyVetoException{

        // create session factorys
        LocalSessionFactoryBean sessionFactory1 = new LocalSessionFactoryBean();

        // set the properties
        sessionFactory1.setDataSource(getDataSource2());
        sessionFactory1.setPackagesToScan(env.getProperty("ds.hibernate.packagesToScan2"));
        sessionFactory1.setHibernateProperties(getHibernateProperties2());

        return sessionFactory1;
    }


    @Autowired
    @Bean(name = "transactionManager")
    public HibernateTransactionManager getTransactionManage2(SessionFactory sessionFactory1) {

        // setup transaction manager based on session factory 
        HibernateTransactionManager txManager = new HibernateTransactionManager();

        txManager.setSessionFactory(sessionFactory1);

        return txManager;
    }

}

Dao类:

代码语言:javascript
运行
复制
package com.pack1.dao;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;

@Repository
public class DataDAO extends JdbcDaoSupport {


     @Autowired
     @Qualifier(value="t1")
     private SessionFactory firstDBSessionFactory;


       public List<Publisher> queryPublishers() {

            // get the current hibernate session
            Session currentSession = firstDBSessionFactory.getCurrentSession();

            // create a query 
            Query<Publisher> theQuery = 
                    currentSession.createQuery("from Publisher", Publisher.class);

            // execute query and get result list
            List<Publisher> customers = theQuery.getResultList();

            // return the results
            return customers;

            return customers;
          }


        @Autowired
        @Qualifier(value="t2")
        private SessionFactory secondDBSessionFactory;


        @Transactional(propagation= Propagation.REQUIRED, readOnly=true, value="t2")
        public List<Advertiser> queryAdvertisers() {

            // get the current hibernate session
            Session currentSession = secondDBSessionFactory.getCurrentSession();

            // create a query 
            Query<Advertiser> theQuery = 
                    currentSession.createQuery("from Advertiser", Advertiser.class);

            // execute query and get result list
            List<Advertiser> customers = theQuery.getResultList();

            // return the results
            return customers;

        }

        }

        public List<String> queryDashboard() {

            return null;
        }
}

属性文件:

代码语言:javascript
运行
复制
# DataSource (PUBLISHER System).

ds.database-driver1=com.mysql.jdbc.Driver
ds.url1=jdbc:mysql://127.0.0.1:3306/pan_db
ds.username1=hbstudent
ds.password1=hbstudent


# DataSource (ADVERTISER System).

ds.database-driver2=com.mysql.jdbc.Driver
ds.url2=jdbc:mysql://127.0.0.1:3306/voter_db
ds.username2=hbstudent
ds.password2=hbstudent


#
# Hibernate properties1
#
ds.hibernate.dialect1=org.hibernate.dialect.MySQLDialect
ds.hibernate.show_sql1=true
ds.hibernate.hbm2ddl.auto1=update


#
# Hibernate properties2
#
ds.hibernate.dialect2=org.hibernate.dialect.MySQLDialect
ds.hibernate.show_sql2=true
ds.hibernate.hbm2ddl.auto2=update

SpringWebAppInitializer类:

代码语言:javascript
运行
复制
package com.pack1.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;

public class SpringWebAppInitializer implements WebApplicationInitializer
{

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {


            AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            ctx.register(ApplicationContextConfig.class);
            ctx.setServletContext(servletContext); // ②

            Dynamic servlet = servletContext.addServlet("dispatcher",new DispatcherServlet(ctx)); // ③
            servlet.addMapping("/*");
            servlet.setLoadOnStartup(1);

            servletContext.addFilter("name", CharacterEncodingFilter.class)
            .addMappingForUrlPatterns(null, false, "/*");

        }



    /*@Override
    public void onStartup(ServletContext servletContext) throws ServletException
    {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(ApplicationContextConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");       
        // 
        dispatcher.setInitParameter("contextClass", appContext.getClass().getName());

        servletContext.addListener(new ContextLoaderListener(appContext));

        // UTF8 Charactor Filter.
        FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);

        fr.setInitParameter("encoding", "UTF-8");
        fr.setInitParameter("forceEncoding", "true");
        fr.addMappingForUrlPatterns(null, true, "/*");
    }*/

    }

WebMvcConfigurerAdapter类:

代码语言:javascript
运行
复制
package com.pack1.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.pack1.intercepter.DataSourceIntercepter;


@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter{

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
    {

        // Default..
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    //
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(new DataSourceIntercepter())//
                .addPathPatterns("/publisher/*", "/advertiser/*");
    }
}

以下是例外情况:

代码语言:javascript
运行
复制
INFO: Server startup in [8,376] milliseconds
Dec 05, 2019 12:05:18 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /multiple_DB1/
Dec 05, 2019 12:05:22 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /multiple_DB1/
Dec 05, 2019 12:05:23 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping for GET /multiple_DB1/

对于在Spring MVC中使用多个数据源,我是个新手。请帮我在Hibernate Configuration类中编码。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-12-03 15:40:03

找到下面的配置文件

代码语言:javascript
运行
复制
package com.yogendra.configuration;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
public class DatabaseConfiguration {

@Autowired
private Environment env;

@Bean("datasource1")
public DataSource dataSource1() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("app1.db.driverClassName"));
    dataSource.setUrl(env.getProperty("app1.db.URL"));
    dataSource.setUsername(env.getProperty("app1.db.username"));
    dataSource.setPassword(env.getProperty("app1.db.password"));
    return dataSource;
}

@Bean("datasource2")
public DataSource dataSource2() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("app2.db.driverClassName"));
    dataSource.setUrl(env.getProperty("app2.db.URL"));
    dataSource.setUsername(env.getProperty("app2.db.username"));
    dataSource.setPassword(env.getProperty("app2.db.password"));
    return dataSource;
}

@Bean("jdbc1")
public JdbcTemplate jdbcTemplate1() {
    return new JdbcTemplate(dataSource1());
}

@Bean("jdbc2")
public JdbcTemplate jdbcTemplate2() {
    return new JdbcTemplate(dataSource2());
}

@Bean("session1")
public LocalSessionFactoryBean sessionFactory1() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource1());
    sessionFactory.setPackagesToScan(new String[] { "com.yogendra" });
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
}

@Bean("session2")
public LocalSessionFactoryBean sessionFactory2() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource2());
    sessionFactory.setPackagesToScan(new String[] { "com.yogendra" });
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
}

@Bean("tx1")
public HibernateTransactionManager transactionManager1() {
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory1().getObject());
    return transactionManager;
}

@Bean("tx2")
public HibernateTransactionManager transactionManager2() {
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory2().getObject());
    return transactionManager;
}

@SuppressWarnings("serial")
private Properties hibernateProperties() {
    return new Properties() {
        {
            setProperty("hibernate.hbm2ddl.auto", "none");
            setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
            setProperty("hibernate.show_sql", "true");
        }
    };
 }

 }

下面是属性文件

代码语言:javascript
运行
复制
 app1.db.driverClassName=org.postgresql.Driver
 app1.db.URL=jdbc:postgresql://localhost/test_db
 app1.db.username=postgres
 app1.db.password=postgres


 app2.db.driverClassName=org.postgresql.Driver
 app2.db.URL=jdbc:postgresql://localhost/test_db2
 app2.db.username=postgres
 app2.db.password=postgres

你可以找到工作代码here

了解如何使用sessionFactory

代码语言:javascript
运行
复制
   @Autowired
   @Qualifier("session2")
   SessionFactory sessionFactory;

   @GetMapping(value = "/test2")
   @Transactional("tx2")
   public void test2() {
    List<String> cities = sessionFactory.getCurrentSession().createSQLQuery("select city from address")
            .list();
    System.out.println("------------ citties ------------ " + cities);
}
票数 1
EN

Stack Overflow用户

发布于 2019-11-30 22:02:34

每个数据库都需要多个配置文件,其中一个需要声明为Primary。我给你提供了一些例子,让你知道你需要什么。

PrimaryDB被声明为项目的主数据库。Primary意味着默认情况下JPA将在主数据库上执行。

代码语言:javascript
运行
复制
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "primaryEntityManagerFactory",
    basePackages = {"com.example.repositories.primary"})
public class PrimaryDBConfig {

  @Primary
  @Bean(name = "primaryDatasource")
  @ConfigurationProperties(prefix = "primary.datasource")
  public DataSource dataSource() {
    return DataSourceBuilder.create().build();
  }

  @Primary
  @Bean(name = "primaryEntityManagerFactory")
  public LocalContainerEntityManagerFactoryBean entityManagerFactory(
      EntityManagerFactoryBuilder builder, @Qualifier("primaryDatasource") DataSource dataSource) {
    return builder.dataSource(dataSource).packages("com.example.entities.primary")
        .persistenceUnit("primary").build();
  }

  @Primary
  @Bean(name = "primaryTransactionManager")
  public PlatformTransactionManager transactionManager(
      @Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);

  }
}

关于第二个数据库FooDB的第二个配置文件

代码语言:javascript
运行
复制
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "fooEntityManagerFactory",
    basePackages = {"com.example.repositories.foo"})
public class FooDBConfig {

  @Bean(name = "fooDatasource")
  @ConfigurationProperties(prefix = "foo.datasource")
  public DataSource dataSource() {
    return DataSourceBuilder.create().build();
  }

  @Bean(name = "fooEntityManagerFactory")
  public LocalContainerEntityManagerFactoryBean entityManagerFactory(
      EntityManagerFactoryBuilder builder, @Qualifier("fooDatasource") DataSource dataSource) {
    return builder.dataSource(dataSource).packages("com.example.entities.crf")
        .persistenceUnit("foo").build();
  }

  @Bean(name = "fooTransactionManager")
  public PlatformTransactionManager transactionManager(
      @Qualifier("fooEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
    return new JpaTransactionManager(entityManagerFactory);
  }
}

此外,您还需要在application.properties上添加以下内容,因为Spring将侦听默认的数据源配置。

代码语言:javascript
运行
复制
primary.datasource.url= URL
primary.datasource.username=username
primary.datasource.password=password


foo.datasource.url=URL
foo.datasource.username=username
foo.datasource.password=password
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59116197

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档