2013-08-13 3 views
13

Spring과 Mybatis로 작업하고 있는데 두 데이터베이스가 있습니다. 첫 번째 데이터베이스의 구성은 상대적으로 쉽지만 Spring과 트랜잭션을 사용하여 두 번째 데이터베이스를 작동시킬 수는 없습니다. 내 코드Mybatis Spring 다중 데이터베이스 Java 구성

@Configuration 
@ComponentScan(basePackages = {"hernandez.service", "hernandez.dao"}) 
@EnableTransactionManagement 
@MapperScan(basePackages="hernandez.mapper") 
@Import(DbConfig2.class) 
public class AppConfig { 

@Bean(name = "dataSource") 
public DataSource dataSource() { 
    DriverManagerDataSource ds = new DriverManagerDataSource("com.mysql.jdbc.Driver", 
      "jdbc:mysql://localhost:3306/northwind", "root", ""); 
    return ds; 
} 

@Bean 
public SqlSessionFactoryBean sqlSessionFactory() { 
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); 
    factoryBean.setDataSource(dataSource()); 
    return factoryBean; 
} 

@Bean(name = "transactionManager") 
public PlatformTransactionManager transactionManager() { 
    return new DataSourceTransactionManager(dataSource()); 
} 
} 

@Configuration 
@MapperScan("loli.mapper") 
public class DbConfig2 { 
@Bean(name = "dataSource_2") 
public DataSource dataSource2() { 
    DriverManagerDataSource ds = new DriverManagerDataSource("com.mysql.jdbc.Driver", 
      "jdbc:mysql://localhost:3306/dmsolut_dmsms", "root", ""); 
    return ds; 
} 

@Bean 
public SqlSessionFactory sqlSessionFactory2() throws Exception{ 
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); 
    factoryBean.setDataSource(dataSource2()); 
    return factoryBean.getObject(); 
} 

@Bean(name = "transactionManager_2") 
public PlatformTransactionManager transactionManager() { 
    return new DataSourceTransactionManager(dataSource2()); 
} 
} 

순수한 봄 자바 구성 또는 적어도 일부 XML 작업이 얻을 수있는 방법이 있나요입니까? Mybatis-Spring 프로젝트에서 두 개의 데이터베이스가 작동하도록하는 공식 문서가 없습니다.

답변

17

mybatis가있는 다중 데이터 소스가 현재 내 프로젝트에서 사용됩니다. 이 예입니다, 당신의 application.xml을에 우리가 우리의 프로젝트에서 사용하는 자바 구성 예와

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="${center.connectionURL}"/> 
    <property name="username" value="${userName}"/> 
    <property name="password" value="${password}"/> 
</bean> 

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
    <property name="basePackage" value="com.xxx.dao.center"/> 
    <property name="sqlSessionFactoryBeanName" value="cneterSqlSessionFactory"/> 
</bean> 

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" name="cneterSqlSessionFactory"> 
    <property name="dataSource" ref="dataSource"></property> 
    <property name="mapperLocations" value="classpath*:mapperConfig/center/*.xml"/> 
    <property name="configLocation" value="classpath:mybatis-config.xml"/> 
</bean> 

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 
<tx:annotation-driven transaction-manager="transactionManager"/> 
<!--center db end--> 
<!--exdb--> 
<bean id="dataSourceEx" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="${ex.connectionURL}"/> 
    <property name="username" value="${userName}"/> 
    <property name="password" value="${password}"/> 
</bean> 
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
    <property name="basePackage" value="com.xxx.dao.ex"/> 
    <property name="sqlSessionFactoryBeanName" value="exSqlSessionFactory"/> 
</bean> 
<bean id="sqlSessionFactoryEx" class="org.mybatis.spring.SqlSessionFactoryBean" name="exSqlSessionFactory"> 
    <property name="dataSource" ref="dataSourceEx"></property> 
    <property name="mapperLocations" value="classpath*:mapperConfig/ex/*.xml"/> 
    <property name="configLocation" value="classpath:mybatis-config.xml"/> 
</bean> 
<bean id="transactionManagerEx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSourceEx"/> 
</bean> 
+7

Java 구성을 사용하여이를 수행 할 수있는 방법이 있습니까? –

+0

아직 시도하지 않았습니다. XML 설정에 의해 mybatis 만 봄과 함께 사용합니다. –

10

추가 답변 추가 : 내 경험에

import org.apache.ibatis.session.SqlSessionFactory; 
import org.apache.ibatis.type.JdbcType; 
import org.mybatis.spring.SqlSessionFactoryBean; 
import org.mybatis.spring.mapper.MapperScannerConfigurer; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.jdbc.datasource.DataSourceTransactionManager; 
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup; 
import org.springframework.transaction.PlatformTransactionManager; 
import org.springframework.transaction.annotation.EnableTransactionManagement; 

import javax.sql.DataSource; 

@Configuration 
@ComponentScan(basePackages = "com.mycompany") 
@EnableTransactionManagement(proxyTargetClass = true) 
public class ApplicationConfig2 { 
    public static final String DATA_SOURCE_NAME_1 = "jdbc/dataSource1"; 
    public static final String DATA_SOURCE_NAME_2 = "jdbc/dataSource2"; 

    public static final String SQL_SESSION_FACTORY_NAME_1 = "sqlSessionFactory1"; 
    public static final String SQL_SESSION_FACTORY_NAME_2 = "sqlSessionFactory2"; 

    public static final String MAPPERS_PACKAGE_NAME_1 = "com.mycompany.mappers.dao1"; 
    public static final String MAPPERS_PACKAGE_NAME_2 = "com.mycompany.mappers.dao2"; 

    @Bean 
    public DataSource dataSource1() { 
     JndiDataSourceLookup dsLookup = new JndiDataSourceLookup(); 
     return dsLookup.getDataSource(DATA_SOURCE_NAME_1); 
    } 

    @Bean 
    public DataSource dataSource2() { 
     JndiDataSourceLookup dsLookup = new JndiDataSourceLookup(); 
     return dsLookup.getDataSource(DATA_SOURCE_NAME_2); 
    } 

    @Bean 
    public PlatformTransactionManager transactionManager() { 
     return new DataSourceTransactionManager(dataSource()); 
    } 


    @Bean(name = SQL_SESSION_FACTORY_NAME_1) 
    public SqlSessionFactory sqlSessionFactory1(DataSource dataSource1) throws Exception { 
     SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); 
     sqlSessionFactoryBean.setTypeHandlersPackage(DateTimeTypeHandler.class.getPackage().getName()); 
     sqlSessionFactoryBean.setDataSource(dataSource1); 
     SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject(); 
     sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true); 
     sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL); 
     return sqlSessionFactory; 
    } 

    @Bean(name = SQL_SESSION_FACTORY_NAME_2) 
    public SqlSessionFactory sqlSessionFactory2(DataSource dataSource2) throws Exception { 
     SqlSessionFactoryBean diSqlSessionFactoryBean = new SqlSessionFactoryBean(); 
     diSqlSessionFactoryBean.setTypeHandlersPackage(DateTimeTypeHandler.class.getPackage().getName()); 
     diSqlSessionFactoryBean.setDataSource(dataSource2); 
     SqlSessionFactory sqlSessionFactory = diSqlSessionFactoryBean.getObject(); 
     sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true); 
     sqlSessionFactory.getConfiguration().setJdbcTypeForNull(JdbcType.NULL); 
     return sqlSessionFactory; 
    } 

    @Bean 
    public MapperScannerConfigurer mapperScannerConfigurer1() { 
     MapperScannerConfigurer configurer = new MapperScannerConfigurer(); 
     configurer.setBasePackage(MAPPERS_PACKAGE_NAME_1); 
     configurer.setSqlSessionFactoryBeanName(SQL_SESSION_FACTORY_NAME_1); 
     return configurer; 
    } 

    @Bean 
    public MapperScannerConfigurer mapperScannerConfigurer2() { 
     MapperScannerConfigurer configurer = new MapperScannerConfigurer(); 
     configurer.setBasePackage(MAPPERS_PACKAGE_NAME_2); 
     configurer.setSqlSessionFactoryBeanName(SQL_SESSION_FACTORY_NAME_2); 
     return configurer; 
    } 
} 
+1

transactionManager는 어떻습니까? 어느 dataSource를 사용해야합니까? –

+0

때때로 datasource, transactionManager 및 SqlSessionFactory를 모두 primary로 할당해야 할 수도 있습니다. –

2

을, 당신은 또한 중 하나에 @Primary를 추가해야 DataSource 빈. 그렇지 않으면 NoUniqueBeanDefinitionException이 전달됩니다.

@Bean 
@Primary 
public DataSource dataSource1() { 
    JndiDataSourceLookup dsLookup = new JndiDataSourceLookup(); 
    return dsLookup.getDataSource(DATA_SOURCE_NAME_1); 
} 

@Bean 
public DataSource dataSource2() { 
    JndiDataSourceLookup dsLookup = new JndiDataSourceLookup(); 
    return dsLookup.getDataSource(DATA_SOURCE_NAME_2); 
} 
1

당신은 그것을 확장하고 방법 determineCurrentLookupKey()를 재정 의하여 봄의 AbstractRoutingDataSource를 사용할 수 있습니다.

봄 구성

당신은 봄 구성에서 별도의 datasource을 정의 할 수 있습니다.

<!-- db2 data source --> 
<bean id="db2DataSource" class="com.ibm.db2.jdbc.app.DB2Driver"> 
    <property name="serverName" value="${db2.jdbc.serverName}" /> 
    <property name="portNumber" value="${db2.jdbc.portNumber}" /> 
    <property name="user" value="${db2.jdbc.username}" /> 
    <property name="password" value="${db2.jdbc.password}" /> 
    <property name="databaseName" value="${db2.jdbc.databaseName}" /> 
</bean> 

<!-- mysql data source --> 
<bean id="mysqlDataSource" class="com.mysql.jdbc.Driver"> 
    <property name="serverName" value="${mysql.jdbc.serverName}" /> 
    <property name="portNumber" value="${mysql.jdbc.portNumber}" /> 
    <property name="user" value="${mysql.jdbc.username}" /> 
    <property name="password" value="${mysql.jdbc.password}" /> 
    <property name="databaseName" value="${mysql.jdbc.databaseName}" /> 
</bean> 

준 고객과 데이터 소스 :

<bean id="customer" class="com.example.Customer"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

<bean id="dataSource" class="com.example.datasource.CustomerRoutingDataSource"> 
    <property name="targetDataSources"> 
    <map key-type="com.example.Customer"> 
    <entry key="db2" value-ref="mysqlDataSource"/> 
    <entry key="mysql" value-ref="db2DataSource"/> 
    </map> 
    </property> 
    <property name="defaultTargetDataSource" ref="mysql"/> 
</bean> 

자바 기본적으로

package com.example; 

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 

public class CustomerRoutingDataSource extends AbstractRoutingDataSource { 

@Bean 
CustomerContextHolder context; 

@Override 
protected Object determineCurrentLookupKey() { 
    return context.getCustomerType(); 
} 
} 

각 요청의 컨텍스트가됩니다. 매핑 된 키를 사용하여 datasource을 요청과 연결할 수 있습니다. 당신은 위에서 언급 한 바와 같이, 우리는 당신의 DaoImpl에서 SessionFactory를 해당 줄 필요가 여기 dynamic-datasource-routing

0

<bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource1" /> 
    <property name="configLocation"> 
     <value>classpath:com/dtcc/dao/impl/DaoSqlMapConfig_MyBatis1.xml</value> 
    </property> 
    <property name="transactionFactory"> 
     <bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" /> 
    </property> 
    <property name="mapperLocations" value="classpath*:com/dtcc/dao/impl/DaoEmfMyBatis.sp.xml"/> 
</bean> 
<bean id="sqlSession1" class="org.mybatis.spring.SqlSessionTemplate"> 
    <constructor-arg index="0" ref="sqlSessionFactory1" /> 
</bean> 
<!-- MyBatis Changes Ends --> 

<bean id="daoEmf" class="com.dtcc.dao.DaoEmfImpl"> 
    <property name="connectionType"><ref local="com.dtcc.sharedservices.utils.resources.ConnTypes.IBM_DB2_CONNECTION" /></property> 
    <property name="jndiNameForLogging"><ref local="dataSourceName1" /></property> 
    <property name="sqlSessionTemplate"> <ref local="sqlSession1" /></property> 
    <property name="applicationLog"><ref local="appLog" /></property> 
</bean> 

자세한 내용을 확인할 수 있습니다. 둘 이상의 sessionFactory가있는 경우 DaoImpl 클래스에서 SqlSessionTemplate을 자동으로 호출 할 수 없습니다. 각 세션 팩토리에 대해 고유 한 이름을 지정하고 해당 DaoImpl 클래스에 매핑하십시오. DaoImpl 클래스에서 Setter 메서드를 사용하여 SqlSessionTemplate에 대한 개체를 만들고 다음과 같이 sqlSessionTemplate 개체를 사용하여 db 호출을 만들 수 있습니다. this.sqlSessionTemplate.selectList ("ProcedureID", 매개 변수);

관련 문제