天天看点

mybatis多数据源配置mybatis的多数据源配置

mybatis的多数据源配置

mybatis是一种比较常用的持久化框架,广泛被开发人员所使用。但在开发中,常常会遇到一个项目要访问多个数据源的情况,如何解决这种问题呢?网上的解决思路大概两种,第一种就是动态切换数据源(需要配合自定义注解和切面拦截实现),第二种就是对不同数据源所涉及到的映射文件和接口进行分包。今天要介绍的第二种实现方式,实现起来也较为简单。

mybatis多数据源配置mybatis的多数据源配置

1. 数据源配置

server.port=8099
oracle.datasource.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
oracle.datasource.username=cs_info
oracle.datasource.password=123456
oracle.datasource.driver=oracle.jdbc.driver.OracleDriver

all.datasource.maxActive=20

mysql.datasource.url=jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf-8
mysql.datasource.username=root
mysql.datasource.password=123456
mysql.datasource.driver=com.mysql.jdbc.Driver
           

配置文件中存在两个数据源,为了方便区分,我们将其称为 mysql数据源和Oracle数据源。

2.Springboot配置类整合mybatis

利用spring来管理mybatis,所配置的内容通过配置类去编写,为了区分不同的数据源,我分为了两个配置类,分别管理不同的数据源。

1.数据源读取

@Component
public class DbPropertiesByAuto {

	@Value("${mysql.datasource.url}")
	public  String mysqlurl;
	
	@Value("${mysql.datasource.username}")
	public  String mysqlusername;
	
	@Value("${mysql.datasource.password}")
	public  String mysqlpwd;
	
	@Value("${mysql.datasource.driver}")
	public  String mysqldirver;
	
	@Value("${all.datasource.maxActive}")
	public  int maxActive;
	
	@Value("${oracle.datasource.url}")
	public  String oracleurl;
	
	@Value("${oracle.datasource.username}")
	public  String oracleusername;
	
	@Value("${oracle.datasource.password}")
	public  String oraclepwd;
	
	@Value("${oracle.datasource.driver}")
	public  String oracledirver;
}
           

2.mysql数据源

@Configuration
@MapperScan(basePackages="com.wang.dao.mysql",sqlSessionFactoryRef="mysql_sqlSessionFactory")
public class MysqlDbConfig {
	
	@Autowired
	DbPropertiesByAuto dbPropertiesByAuto;
	
	@Bean("mysqlDataSource")
	public DataSource mysqlDataSource() {
		DruidDataSource mysqlDataSource=new DruidDataSource();
		mysqlDataSource.setDriverClassName(dbPropertiesByAuto.mysqldirver);
		mysqlDataSource.setUrl(dbPropertiesByAuto.mysqlurl);
		mysqlDataSource.setUsername(dbPropertiesByAuto.mysqlusername);
		mysqlDataSource.setPassword(dbPropertiesByAuto.mysqlpwd);
		mysqlDataSource.setMaxActive(dbPropertiesByAuto.maxActive);
		return mysqlDataSource;
	}
	
	@Bean("mysql_sqlSessionFactory")
	public SqlSessionFactory mysql_sqlSessionFactory(@Qualifier("mysqlDataSource")DataSource mysqlDataSource) throws Exception {
		SqlSessionFactoryBean mysql_sqlSession=new SqlSessionFactoryBean();
		mysql_sqlSession.setDataSource(mysqlDataSource);
		Resource configLocation = new ClassPathResource("mybatis-mysql-config.xml"); 
        mysql_sqlSession.setConfigLocation(configLocation);
		mysql_sqlSession.setTypeAliasesPackage("com.wang.bean");
		PathMatchingResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
		Resource[] mapperLocations=resolver.getResources("classpath:com/wang/mapper/mysql/*.xml");
		mysql_sqlSession.setMapperLocations(mapperLocations);
		return mysql_sqlSession.getObject();
		
	}
	
	@Bean("mysqlTransactionManager")
	public PlatformTransactionManager mysqlTransactionManager(@Qualifier("mysqlDataSource")DataSource mysqlDataSource) {
		DataSourceTransactionManager mysqlTransactionManager=new DataSourceTransactionManager() ;
		mysqlTransactionManager.setDataSource(mysqlDataSource);
		return mysqlTransactionManager;
	}
	
}
           

整合mybatis,需要配置SqlSessionFactory ,这是管理sqlSession的工厂,非常重要。以上代码可以看出,sqlsessionfactory设置了 datasource 、mybatis的配置文件位置、Mapper映射文件的存放位置等。

除此之外 ,该配置类引用了@MapperScan 注解,这是指定要扫描的Mapper类的包的路径,值得注意的是,还有个sqlSessionFactoryRef属性,通常只有一个sqlsessionfactory(一个数据源)时,可以不用指定,现在是多数据源,必须指定。如果不想使用@MapperScan,还可以用下面这种方式实现

@Bean("mysqlMapperScannerConfigurer")
	public MapperScannerConfigurer mysqlMapperScannerConfigurer() {
		MapperScannerConfigurer scannerConfigurer=new MapperScannerConfigurer();
		scannerConfigurer.setSqlSessionFactoryBeanName("mysql_sqlSessionFactory");
		scannerConfigurer.setBasePackage("com.wang.dao.mysql");
		return scannerConfigurer;
	}
           

3.oracle数据源

@Configuration
@MapperScan(basePackages="com.wang.dao.oracle",sqlSessionFactoryRef="oracle_sqlSessionFactory")
public class OracleDbConfig {
	
	@Autowired
	DbPropertiesByAuto dbPropertiesByAuto;
	
	@Bean("oracleSource")
	@Primary
	public DataSource oracleSource() {
		DruidDataSource oracleDataSource=new DruidDataSource();
		oracleDataSource.setDriverClassName(dbPropertiesByAuto.oracledirver);
		oracleDataSource.setUrl(dbPropertiesByAuto.oracleurl);
		oracleDataSource.setUsername(dbPropertiesByAuto.oracleusername);
		oracleDataSource.setPassword(dbPropertiesByAuto.oraclepwd);
		oracleDataSource.setMaxActive(dbPropertiesByAuto.maxActive);
		return oracleDataSource;
	}
	
	
	@Bean("oracle_sqlSessionFactory")
	@Primary
	public SqlSessionFactory oracle_sqlSessionFactory(@Qualifier("oracleSource")DataSource oracleSource) throws Exception {
		SqlSessionFactoryBean oracle_sqlSession=new SqlSessionFactoryBean();
		oracle_sqlSession.setDataSource(oracleSource);
		Resource configLocation = new ClassPathResource("mybatis-oracle-config.xml"); 
        oracle_sqlSession.setConfigLocation(configLocation);
		oracle_sqlSession.setTypeAliasesPackage("com.wang.bean");
		PathMatchingResourcePatternResolver resolver=new PathMatchingResourcePatternResolver();
		Resource[] mapperLocations=resolver.getResources("classpath:com/wang/mapper/oracle/*.xml");
		oracle_sqlSession.setMapperLocations(mapperLocations);
		return oracle_sqlSession.getObject();
		
	}
	
	@Bean("oracleTransactionManager")
	public PlatformTransactionManager oracleTransactionManager(@Qualifier("oracleSource")DataSource oracleSource ) {
		DataSourceTransactionManager oracleTransactionManager=new DataSourceTransactionManager() ;
		oracleTransactionManager.setDataSource(oracleSource);
		return oracleTransactionManager;
	}
	
	
}
           

原理与mysql数据源配置相同,不再赘述。

4.mybatis配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!--配置全局属性 -->
	<settings>
		<!--使用列别名替换列名 默认值为true(可以不用写出来,这里写出来只是为了讲解该配置的作用)
			select name as title(实体中的属性名是title) form table; 
			开启后mybatis会自动帮我们把表中name的值赋到对应实体的title属性中 -->
		<setting name="useColumnLabel" value="true" />

		<!--开启驼峰命名转换Table:create_time到 Entity(createTime) -->
		<setting name="mapUnderscoreToCamelCase" value="true" />
		<setting name="logImpl" value="STDOUT_LOGGING" /> 
	</settings>

</configuration>
           

3.编写xml映射文件和Mapper接口

配置完mybatis之后,其实就可以正常开发了,需要注意的是,不同的数据源指定了对应的映射文件和Mapper类位置,映射文件和mapper接口要放在对应的包中。下面贴出mysql数据源的代码

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace:指定为哪个接口提供配置 --> 
<mapper namespace="com.wang.dao.mysql.SeckillDao">
	<!--目的:为dao接口方法提供sql语句配置, 即针对dao接口中的方法编写我们的sql语句 -->

	 <!-- parameterType:使用到的参数类型
		正常情况java表示一个类型的包名+类名,这直接写类名,因为后面有一个配置可以简化写包名的过程 -->
	<select id="queryById" resultType="Seckill" parameterType="long">
		<!-- 可以通过别名的方式列明到java名的转换,如果开启了驼峰命名法就可以不用这么写了 
       		 select seckill_id as seckillId
        -->
		SELECT seckill_id,name,number,create_time,start_time,end_time
		FROM seckill
		WHERE seckill_id= #{seckillId}
	</select>

	<select id="queryAll" resultType="Seckill">
		SELECT *
		FROM seckill
		ORDER BY create_time DESC
	</select>
	
	<insert id="insertSeckill" parameterType="Seckill">
		INSERT INTO seckill
		(
		  seckill_id
		  , name
		  , number
		  , create_time
		  , start_time
		  , end_time
		)
		VALUES
		(
		  #{seckillId}
		  , #{name}
		  , #{number}
		  , #{createTime}
		  , #{startTime}
		  , #{endTime}
		)
	</insert>
	
	<update id="updateSeckill" parameterType="Seckill">
		update seckill set number=#{number}
		<if test="name!=null">
			, name=#{name} 
		</if>  
	     where seckill_id=#{seckillId}
	</update>
</mapper>
           
package com.wang.dao.mysql;

import java.util.List;

import com.wang.bean.Seckill;

public interface SeckillDao {

	/**
	 * 根据id查询秒杀商品
	 * 
	 * @param seckillId
	 * @return
	 */
	Seckill queryById(long seckillId);
	/**
	 * 查询全部
	 * @return
	 */
	List<Seckill>queryAll();
	
	void insertSeckill(Seckill seckill);
	
	void updateSeckill(Seckill seckill);
}
           

4.测试

@Resource
	private SeckillDao seckillDao;

	public List<Seckill> queryAll(){
		List<Seckill>seckills= seckillDao.queryAll();
		return seckills;
	}
	@Transactional(value="mysqlTransactionManager" ,propagation=Propagation.REQUIRED)
	public void dbOperateWithShiwu() {
		update();
		insert();
	}
	
	public void insert() {
		Seckill seckill=new Seckill();
		setValue(seckill);
		seckillDao.insertSeckill(seckill);
	}
	
	public void update() {
		Seckill seckill=seckillDao.queryById(1008L);
		seckill.setName(seckill.getName()+"--修改");
		seckillDao.updateSeckill(seckill);
	}
           

通过测试,发现使用不同包下的mapper接口,可以操作不同的数据源。以上代码中,我们可以看到使用了事务,不同的数据源定义不同的事务,在业务层指定事务就可以使用了。

源代码地址

继续阅读