SpringBoot 集成多数据源
一个项目中怎么划分数据库,可以通过具体业务需求。
项目中数据源怎么如何划分,通过注解的方式@Datasource(ref="") 在方法上指定,会连接指定的数据源,这种方式比较繁琐。如果有1000个方法,就得写1000个这种注解。所以一般通过分包名的方式。
通过分包名来划分数据源:
1,mysql 里面有两个库,testdb,testdb2,里面各有一张user表,数据结构是一样的
2,建立实体类:user
@Data //相当于@Setter @Getter public class User { private int id; private String username; private String sex; private Date birthday; private String address; }
2,datasource 包下有DataSource1Config,DataSource2Config,如下:
package com.baiyue.datasource; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; // DataSource01 @Configuration // 注册到springboot容器中 @MapperScan(basePackages = "com.baiyue.db1", sqlSessionFactoryRef = "db1SqlSessionFactory") public class DataSource1Config { @Bean(name = "db1DataSource") //@Bean是注入到Spring 容器中 @ConfigurationProperties(prefix = "spring.datasource.db1")//读取配置文件中以spring.datasource.db1 开头的 public DataSource testDataSource() { return DataSourceBuilder.create().build(); } @Primary @Bean(name = "db1SqlSessionFactory") public SqlSessionFactory testSqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath:com/baiyue/db1/mapping/*Mapper.xml")); return bean.getObject(); } /** * 事务 */ @Bean(name = "db1TransactionManager") public DataSourceTransactionManager testTransactionManager(@Qualifier("db1DataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "db1SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate( @Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
DataSource2:
package com.baiyue.datasource; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; // DataSource01 @Configuration // 注册到springboot容器中 @MapperScan(basePackages = "com.baiyue.db2", sqlSessionFactoryRef = "db2SqlSessionFactory") public class DataSource2Config { @Bean(name = "db2DataSource") //@Bean是注入到Spring 容器中 @ConfigurationProperties(prefix = "spring.datasource.db2")//读取配置文件中以spring.datasource.db2 开头的 public DataSource testDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "db2SqlSessionFactory") public SqlSessionFactory testSqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath:com/baiyue/db2/mapping/*Mapper.xml")); return bean.getObject(); } /** * 事务 */ @Bean(name = "db2TransactionManager") public DataSourceTransactionManager testTransactionManager(@Qualifier("db2DataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "db2SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate( @Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
通过 @Configuration // 注册到springboot容器中,在启动类中会去读取所有的Bean,通过两个类以及配置文件,能够获取到不同包下的业务层对应不同的数据源..
#多数据源 spring: datasource: db1: driver-class-name: com.mysql.jdbc.Driver jdbcUrl: jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf-8 username: root password: 123456 db2: driver-class-name: com.mysql.jdbc.Driver jdbcUrl: jdbc:mysql://localhost:3306/testdb2?useUnicode=true&characterEncoding=utf-8 username: root password: 123456
3,db1 下的mapper,xml,service,sevice层需要指定业务相应的事务管理,否则会报有两个事务管理的错
package com.baiyue.db1.mapper; import com.baiyue.entity.User; public interface UserMapperdb1 { void insertUser(User user); User selectUserById(int id); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.baiyue.db1.mapper.UserMapperdb1"> <!-- 根据 id 查询 user 表中的数据 id:唯一标识符,此文件中的id值不能重复 resultType:返回值类型,一条数据库记录也就对应实体类的一个对象 parameterType:参数类型,也就是查询条件的类型 --> <select id="selectUserById" resultType="com.baiyue.entity.User" parameterType="int"> <!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 --> select * from user where id = #{id} </select> <insert id="insertUser" parameterType="com.baiyue.entity.User"> insert into user(id,username,sex,birthday,address) value(#{id},#{username},#{sex},#{birthday},#{address}) </insert> </mapper>
package com.baiyue.db1.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.baiyue.db1.mapper.UserMapperdb1; import com.baiyue.entity.User; import lombok.extern.slf4j.Slf4j; @Service @Slf4j public class UserServicedb1 { @Override public String toString() { // TODO Auto-generated method stub return super.toString(); } @Autowired private UserMapperdb1 userMapper; @Transactional("db1TransactionManager")//指定事务管理 public void insertUser(User user) { userMapper.insertUser(user); }; public User selectUserById(int id) { User user = userMapper.selectUserById(id); return user; }; }
4,同理,db2 的mapper,xml,service
package com.baiyue.db2.mapper; import com.baiyue.entity.User; public interface UserMapperdb2 { void insertUser(User user); User selectUserById(int id); }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.baiyue.db2.mapper.UserMapperdb2"> <!-- 根据 id 查询 user 表中的数据 id:唯一标识符,此文件中的id值不能重复 resultType:返回值类型,一条数据库记录也就对应实体类的一个对象 parameterType:参数类型,也就是查询条件的类型 --> <select id="selectUserById" resultType="com.baiyue.entity.User" parameterType="int"> <!-- 这里和普通的sql 查询语句差不多,对于只有一个参数,后面的 #{id}表示占位符,里面不一定要写id,写啥都可以,但是不要空着,如果有多个参数则必须写pojo类里面的属性 --> select * from user where id = #{id} </select> <insert id="insertUser" parameterType="com.baiyue.entity.User"> insert into user(id,username,sex,birthday,address) value(#{id},#{username},#{sex},#{birthday},#{address}) </insert> </mapper>
package com.baiyue.db2.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.baiyue.db2.mapper.UserMapperdb2; import com.baiyue.entity.User; import lombok.extern.slf4j.Slf4j; @Service @Slf4j public class UserServicedb2 { @Autowired private UserMapperdb2 userMapper; @Transactional("db2TransactionManager")//指定事务管理 public void insertUser(User user) { log.info("正在添加"); userMapper.insertUser(user); }; public User selectUserById(int id) { User user = userMapper.selectUserById(id); return user; }; }
5,controller 层:
package com.baiyue.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.baiyue.db1.service.UserServicedb1; import com.baiyue.db2.service.UserServicedb2; import com.baiyue.entity.User; @RestController public class Mybatis { @Autowired private UserServicedb1 userService1; @Autowired private UserServicedb2 userService2; @RequestMapping("/insertUserdb1") public String insertUserdb1(){ User user = new User(); user.setUsername("chris"); user.setSex("male"); userService1.insertUser(user); return "db1success"; } @RequestMapping("/insertUserdb2") public String insertUserdb2() { User user = new User(); user.setUsername("chris"); user.setSex("male"); userService2.insertUser(user); return "db2success"; } }
6,启动类
@MapperScan({"com.baiyue.db1.mapper","com.baiyue.db2.mapper"}) @ComponentScan(basePackages = "com.baiyue") //因为有一些bean 不在当前包或者子包下面,所以@SpringBootApplication 会有些bean 扫不到 @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
这样,能够多数据源操作了。。。
Aimer,c'est partager