21

我正在使用 Spring 和 Mybatis,并且我有两个数据库,第一个数据库的配置相对容易,但是我无法使用 Spring 和事务处理第二个数据库,这是我的代码

@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 项目中工作

4

5 回答 5

24

我的项目中现在使用了带有 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>
于 2013-08-13T07:28:10.380 回答
17

使用我们在项目中使用的 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;
    }
}
于 2015-02-18T14:25:53.183 回答
3

根据我的经验,您还应该添加@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);
}
于 2016-07-26T02:29:09.650 回答
2

您可以通过扩展它并覆盖方法来使用 spring 的AbstractRoutingDataSourcedetermineCurrentLookupKey()

弹簧配置

您可以datasource在 spring 配置中单独定义。

<!-- 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使用映射键与请求相关联。您可以在此处找到更多详细信息dynamic-datasource-routing

于 2017-01-26T23:05:26.933 回答
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>

如上所述,我们需要在你的 DaoImpl 中给出对应的 sessionFactory。如果您有多个 sessionFactory,则不能在 DaoImpl 类中自动装配 SqlSessionTemplate。为每个会话工厂提供唯一名称并将其映射到您各自的 DaoImpl 类。您所要做的就是在 DaoImpl 类中使用 Setter 方法为 SqlSessionTemplate 创建对象,您可以使用 sqlSessionTemplate 对象进行数据库调用,如下所示,this.sqlSessionTemplate.selectList("ProcedureID", parameter);

于 2017-02-03T14:43:01.727 回答