2013-08-13 10 views
13

Sto lavorando con Spring e Mybatis e ho due database, la configurazione per il primo database era relativamente semplice, ma non riesco a lavorare sul secondo database con Spring e transazioni, qui è il mio codiceDatabase multipli Mybatis Spring Configurazione 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()); 
} 
} 

C'è un modo per farlo funzionare con la pura configurazione Spring Java o almeno con un XML? Non esiste una documentazione ufficiale per ottenere due database che funzionano nel progetto Mybatis-Spring

risposta

17

Nel mio progetto sono attualmente utilizzate più origini dati con mybatis. Questo è un esempio, aggiungere alla vostra 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

C'è un modo per farlo utilizzando la configurazione di Java? –

+0

Non ho ancora provato. Io uso mybatis solo con spring by XML config. –

10

Rispondere con l'esempio java config usiamo nel nostro progetto:

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

E il transactionManager? quale dataSource dovrebbe usare? –

+0

A volte potrebbe essere necessario assegnare l'origine dati, transactionManager e SqlSessionFactory come primario. –

2

Nella mia esperienza, si dovrebbe anche aggiungere @Primary ad uno dei DataSource fagioli. Altrimenti lancerà lo 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

È possibile utilizzare la primavera del AbstractRoutingDataSource estendendolo e l'override del metodo determineCurrentLookupKey().

configurazione Primavera

È possibile definire separata datasource in configurazione primavera.

<!-- 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> 

associato l'origine dati con il cliente:

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

In sostanza, ogni richiesta avrà il suo contesto. È possibile associare datasource con richiesta utilizzando la chiave mappata. Potete trovare maggiori dettagli qui 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> 

Come accennato in precedenza, abbiamo bisogno di dare corrispondente sessionFactory nelle vostre DaoImpl. Se non si dispone di più di sessionFactory, non è possibile autorizzare SqlSessionTemplate nella classe DaoImpl. Assegna un nome univoco per ogni factory di sessione e associalo alla tua rispettiva classe DaoImpl. Tutto ciò che dovete fare è solo creare oggetto per SqlSessionTemplate con metodo Setter in classe DaoImpl ed è possibile effettuare la chiamata db usando l'oggetto sqlSessionTemplate come sotto, this.sqlSessionTemplate.selectList ("ProceduraID", parametro);