web-dev-qa-db-ja.com

Mybatis Spring複数データベースJava configuration

私はSpringとMybatisで作業しており、2つのデータベースがあり、最初のデータベースの設定は比較的簡単でしたが、Springとトランザクションで2番目のデータベースを操作することはできません、ここに私のコードがあります

@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());
}
}

これを純粋なSpring Java設定または少なくともXMLで動作させる方法はありますか?Mybatis-Springプロジェクトで動作する2つのデータベースを取得する公式ドキュメントはありません

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>
21
Larry.Z

プロジェクトで使用するJava configの例を使用して回答を追加します。

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;
    }
}
15
moleksyuk

スプリングを拡張し、メソッド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>

Java

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をリクエストに関連付けることができます。詳細はこちらをご覧ください dynamic-datasource-routing

2
fabfas

私の経験では、DataSource Beanのいずれかに@Primaryを追加する必要もあります。それ以外の場合は、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);
}
2
kaibo
<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>

上記のように、DaoImplで対応するsessionFactoryを提供する必要があります。複数のsessionFactoryがある場合、DaoImplクラスでSqlSessionTemplateを自動接続することはできません。各セッションファクトリに一意の名前を付け、それぞれのDaoImplクラスにマップします。 DaoImplクラスのSetterメソッドでSqlSessionTemplateのオブジェクトを作成するだけで、以下のようにsqlSessionTemplateオブジェクトを使用してdb呼び出しを行うことができます。this.sqlSessionTemplate.selectList( "ProcedureID"、parameter);

0
P Frank