├── src ├── main │ ├── resources │ │ ├── application.yml │ │ ├── application-dev.yml │ │ └── logback-spring.xml │ └── java │ │ └── com │ │ └── warm │ │ ├── system │ │ ├── mapper │ │ │ ├── UserMapper.java │ │ │ └── OrderMapper.java │ │ ├── service │ │ │ ├── db1 │ │ │ │ └── UserService.java │ │ │ ├── db2 │ │ │ │ └── OrderService.java │ │ │ └── impl │ │ │ │ ├── OrderServiceImpl.java │ │ │ │ └── UserServiceImpl.java │ │ ├── entity │ │ │ ├── User.java │ │ │ └── Order.java │ │ └── controller │ │ │ └── IndexController.java │ │ ├── common │ │ ├── DBTypeEnum.java │ │ ├── DataSourceSwitch.java │ │ ├── DynamicDataSource.java │ │ ├── DbContextHolder.java │ │ └── DataSourceSwitchAspect.java │ │ ├── DynamicDatasourceApplication.java │ │ └── config │ │ └── mybatis │ │ ├── MyMetaObjectHandler.java │ │ └── MybatisPlusConfig.java └── test │ └── java │ └── com │ └── warm │ ├── DynamicDatasourceApplicationTests.java │ ├── entity │ └── DataTest.java │ └── generator │ └── MpGenerator.java ├── readme.md ├── user.sql ├── t_order.sql └── pom.xml /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: dev -------------------------------------------------------------------------------- /src/main/java/com/warm/system/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.mapper; 2 | 3 | import com.warm.system.entity.User; 4 | import com.baomidou.mybatisplus.mapper.BaseMapper; 5 | 6 | /** 7 | *

8 | * Mapper 接口 9 | *

10 | * 11 | * @author dgd123 12 | * @since 2018-02-10 13 | */ 14 | public interface UserMapper extends BaseMapper { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/warm/common/DBTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.warm.common; 2 | 3 | /** 4 | * @Author DGD 5 | * @date 2018/2/7. 6 | */ 7 | public enum DBTypeEnum { 8 | db1("db1"), db2("db2"); 9 | private String value; 10 | 11 | DBTypeEnum(String value) { 12 | this.value = value; 13 | } 14 | 15 | public String getValue() { 16 | return value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/warm/DynamicDatasourceApplication.java: -------------------------------------------------------------------------------- 1 | package com.warm; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DynamicDatasourceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DynamicDatasourceApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | SpringBoot + MyBatis plus + Mysql 2 | 3 | JDK 版本 1.8 4 | 5 | 用到了lombok插件,使用方法百度 6 | 7 | 创建数据库db1,执行user.sql 8 | 9 | 创建数据库db2,执行t_order.sql 10 | 11 | http://localhost:8080/user 12 | 13 | http://localhost:8080/order 14 | 15 | http://localhost:8080/price 16 | 17 | 参考: 18 | http://baomidou.oschina.io/mybatis-plus-doc/#/multi-datasource?id=%e5%a4%9a%e6%95%b0%e6%8d%ae%e6%ba%90%e4%bd%bf%e7%94%a8-spring-abstractroutingdatasource-%e5%ae%9e%e7%8e%b0 -------------------------------------------------------------------------------- /src/test/java/com/warm/DynamicDatasourceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.warm; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DynamicDatasourceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/warm/common/DataSourceSwitch.java: -------------------------------------------------------------------------------- 1 | package com.warm.common; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @Author DGD 10 | * @date 2018/2/10. 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target({ElementType.METHOD}) 14 | public @interface DataSourceSwitch { 15 | DBTypeEnum value() default DBTypeEnum.db1; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/warm/common/DynamicDataSource.java: -------------------------------------------------------------------------------- 1 | package com.warm.common; 2 | 3 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 4 | 5 | /** 6 | * @Author DGD 7 | * @date 2018/2/7. 8 | */ 9 | public class DynamicDataSource extends AbstractRoutingDataSource { 10 | /** 11 | * 取得当前使用哪个数据源 12 | * @return 13 | */ 14 | @Override 15 | protected Object determineCurrentLookupKey() { 16 | return DbContextHolder.getDbType(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/service/db1/UserService.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.service.db1; 2 | 3 | import com.baomidou.mybatisplus.service.IService; 4 | import com.warm.system.entity.User; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.List; 8 | 9 | /** 10 | *

11 | * 服务类 12 | *

13 | * 14 | * @author dgd123 15 | * @since 2018-02-10 16 | */ 17 | public interface UserService extends IService { 18 | List getUserList(); 19 | 20 | BigDecimal getOrderPriceByUserId(Integer userId); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/service/db2/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.service.db2; 2 | 3 | import com.baomidou.mybatisplus.service.IService; 4 | import com.warm.system.entity.Order; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.List; 8 | 9 | /** 10 | *

11 | * 服务类 12 | *

13 | * 14 | * @author dgd123 15 | * @since 2018-02-10 16 | */ 17 | public interface OrderService extends IService { 18 | List getOrderList(); 19 | BigDecimal getOrderPriceByUserId(Integer userId); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.mapper; 2 | 3 | import com.warm.system.entity.Order; 4 | import com.baomidou.mybatisplus.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Select; 6 | 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | *

11 | * Mapper 接口 12 | *

13 | * 14 | * @author dgd123 15 | * @since 2018-02-10 16 | */ 17 | public interface OrderMapper extends BaseMapper { 18 | @Select("SELECT price from t_order where user_id =#{userId}") 19 | BigDecimal getPriceByUserId(Integer userId); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/warm/common/DbContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.warm.common; 2 | 3 | /** 4 | * @Author DGD 5 | * @date 2018/2/7. 6 | */ 7 | public class DbContextHolder { 8 | private static final ThreadLocal contextHolder = new ThreadLocal<>(); 9 | /** 10 | * 设置数据源 11 | * @param dbTypeEnum 12 | */ 13 | public static void setDbType(DBTypeEnum dbTypeEnum) { 14 | contextHolder.set(dbTypeEnum.getValue()); 15 | } 16 | 17 | /** 18 | * 取得当前数据源 19 | * @return 20 | */ 21 | public static String getDbType() { 22 | return (String) contextHolder.get(); 23 | } 24 | 25 | /** 26 | * 清除上下文数据 27 | */ 28 | public static void clearDbType() { 29 | contextHolder.remove(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | 4 | spring: 5 | aop: 6 | proxy-target-class: true 7 | auto: true 8 | datasource: 9 | druid: 10 | # 数据库 1 11 | db1: 12 | url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true 13 | username: root 14 | password: root 15 | driver-class-name: com.mysql.jdbc.Driver 16 | initialSize: 5 17 | minIdle: 5 18 | maxActive: 20 19 | # 数据库 2 20 | db2: 21 | url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true 22 | username: root 23 | password: root 24 | driver-class-name: com.mysql.jdbc.Driver 25 | initialSize: 5 26 | minIdle: 5 27 | maxActive: 20 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /user.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : 本机 5 | Source Server Version : 50721 6 | Source Host : localhost:3306 7 | Source Database : db1 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50721 11 | File Encoding : 65001 12 | 13 | Date: 2018-02-10 11:29:56 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for user 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `user`; 22 | CREATE TABLE `user` ( 23 | `id` int(11) NOT NULL AUTO_INCREMENT, 24 | `name` varchar(16) DEFAULT NULL COMMENT '姓名', 25 | `age` int(11) DEFAULT NULL COMMENT '年龄', 26 | `create_time` datetime DEFAULT NULL COMMENT '创建时间', 27 | `modify_time` datetime DEFAULT NULL COMMENT '修改时间', 28 | PRIMARY KEY (`id`) 29 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 30 | 31 | -- ---------------------------- 32 | -- Records of user 33 | -- ---------------------------- 34 | INSERT INTO `user` VALUES ('1', 'admin', '22', '2018-02-10 10:11:18', '2018-02-10 10:11:20'); 35 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.service.impl; 2 | 3 | import com.warm.common.DBTypeEnum; 4 | import com.warm.common.DataSourceSwitch; 5 | import com.warm.system.entity.Order; 6 | import com.warm.system.mapper.OrderMapper; 7 | import com.warm.system.service.db2.OrderService; 8 | import com.baomidou.mybatisplus.service.impl.ServiceImpl; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.math.BigDecimal; 13 | import java.util.List; 14 | 15 | /** 16 | *

17 | * 服务实现类 18 | *

19 | * 20 | * @author dgd123 21 | * @since 2018-02-10 22 | */ 23 | @Service 24 | public class OrderServiceImpl extends ServiceImpl implements OrderService { 25 | @Autowired 26 | private OrderMapper orderMapper; 27 | 28 | @Override 29 | public List getOrderList() { 30 | return selectList(null); 31 | } 32 | 33 | @Override 34 | public BigDecimal getOrderPriceByUserId(Integer userId) { 35 | return orderMapper.getPriceByUserId(userId); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.service.impl; 2 | 3 | import com.baomidou.mybatisplus.service.impl.ServiceImpl; 4 | import com.warm.common.DBTypeEnum; 5 | import com.warm.common.DataSourceSwitch; 6 | import com.warm.system.entity.User; 7 | import com.warm.system.mapper.OrderMapper; 8 | import com.warm.system.mapper.UserMapper; 9 | import com.warm.system.service.db1.UserService; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.math.BigDecimal; 14 | import java.util.List; 15 | 16 | /** 17 | *

18 | * 服务实现类 19 | *

20 | * 21 | * @author dgd123 22 | * @since 2018-02-10 23 | */ 24 | @Service 25 | public class UserServiceImpl extends ServiceImpl implements UserService { 26 | @Autowired 27 | private OrderMapper orderMapper; 28 | @Override 29 | public List getUserList() { 30 | return selectList(null); 31 | } 32 | 33 | @DataSourceSwitch(DBTypeEnum.db2) 34 | @Override 35 | public BigDecimal getOrderPriceByUserId(Integer userId) { 36 | return orderMapper.getPriceByUserId(userId); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/warm/entity/DataTest.java: -------------------------------------------------------------------------------- 1 | package com.warm.entity; 2 | 3 | import com.warm.system.service.db1.UserService; 4 | import com.warm.system.service.db2.OrderService; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 | 11 | /** 12 | * @Author DGD 13 | * @date 2018/2/10. 14 | */ 15 | @SpringBootTest 16 | @RunWith(SpringJUnit4ClassRunner.class) 17 | public class DataTest { 18 | @Autowired 19 | private UserService userService; 20 | @Autowired 21 | private OrderService orderService; 22 | 23 | @Test 24 | public void test() { 25 | userService.getUserList().stream().forEach(item -> System.out.println(item)); 26 | orderService.getOrderList().stream().forEach(item -> System.out.println(item)); 27 | } 28 | 29 | /** 30 | * 测试一下注解方式 31 | */ 32 | @Test 33 | public void test2() { 34 | orderService.getOrderList().stream().forEach(item -> System.out.println(item)); 35 | System.out.println(userService.getOrderPriceByUserId(1)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /t_order.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : 本机 5 | Source Server Version : 50721 6 | Source Host : localhost:3306 7 | Source Database : db2 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50721 11 | File Encoding : 65001 12 | 13 | Date: 2018-02-10 11:30:05 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for t_order 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `t_order`; 22 | CREATE TABLE `t_order` ( 23 | `id` int(11) NOT NULL AUTO_INCREMENT, 24 | `order_no` varchar(11) DEFAULT NULL COMMENT '订单号', 25 | `user_id` int(11) DEFAULT NULL COMMENT '用户ID', 26 | `price` decimal(11,2) DEFAULT NULL COMMENT '支付金额', 27 | `paid_time` datetime DEFAULT NULL COMMENT '支付时间', 28 | `create_time` datetime DEFAULT NULL COMMENT '创建时间', 29 | `modify_time` datetime DEFAULT NULL COMMENT '修改时间', 30 | PRIMARY KEY (`id`) 31 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 32 | 33 | -- ---------------------------- 34 | -- Records of t_order 35 | -- ---------------------------- 36 | INSERT INTO `t_order` VALUES ('1', '20180210001', '1', '100.00', '2018-02-10 10:16:11', '2018-02-10 10:16:15', '2018-02-10 10:16:17'); 37 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.entity; 2 | 3 | import com.baomidou.mybatisplus.activerecord.Model; 4 | import com.baomidou.mybatisplus.annotations.TableField; 5 | import com.baomidou.mybatisplus.annotations.TableId; 6 | import com.baomidou.mybatisplus.enums.FieldFill; 7 | import com.baomidou.mybatisplus.enums.IdType; 8 | import lombok.Data; 9 | 10 | import java.io.Serializable; 11 | import java.util.Date; 12 | 13 | /** 14 | *

15 | * 16 | *

17 | * 18 | * @author dgd123 19 | * @since 2018-02-10 20 | */ 21 | @Data 22 | public class User extends Model { 23 | 24 | private static final long serialVersionUID = 1L; 25 | 26 | @TableId(value = "id", type = IdType.AUTO) 27 | private Integer id; 28 | /** 29 | * 姓名 30 | */ 31 | private String name; 32 | /** 33 | * 年龄 34 | */ 35 | private Integer age; 36 | /** 37 | * 创建时间 38 | */ 39 | @TableField(value = "create_time",fill = FieldFill.INSERT) 40 | private Date createTime; 41 | /** 42 | * 修改时间 43 | */ 44 | @TableField(value = "modify_time",fill = FieldFill.INSERT_UPDATE) 45 | private Date modifyTime; 46 | 47 | @Override 48 | protected Serializable pkVal() { 49 | return this.id; 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/warm/config/mybatis/MyMetaObjectHandler.java: -------------------------------------------------------------------------------- 1 | package com.warm.config.mybatis; 2 | 3 | import com.baomidou.mybatisplus.mapper.MetaObjectHandler; 4 | import org.apache.ibatis.reflection.MetaObject; 5 | 6 | import java.sql.Timestamp; 7 | 8 | /** 9 | * @Author DGD 10 | * @date 2018/2/6. 11 | */ 12 | public class MyMetaObjectHandler extends MetaObjectHandler { 13 | 14 | /** 15 | * 字段为空自动填充,如果要使填充生效,一定在在实体类对应的字段上设置fill = FieldFill.INSERT字段! 16 | */ 17 | public void insertFill(MetaObject metaObject) { 18 | // 更多查看源码测试用例 19 | System.out.println("*************************"); 20 | System.out.println("insert fill"); 21 | System.out.println("*************************"); 22 | 23 | Object createTime = getFieldValByName("createTime", metaObject);//mybatis-plus版本2.0.9+ 24 | 25 | Timestamp timestamp = new Timestamp(System.currentTimeMillis()); 26 | if (createTime == null) { 27 | setFieldValByName("createTime", timestamp, metaObject);//mybatis-plus版本2.0.9+ 28 | } 29 | 30 | } 31 | 32 | @Override 33 | public void updateFill(MetaObject metaObject) { 34 | //更新填充 35 | System.out.println("*************************"); 36 | System.out.println("update fill"); 37 | System.out.println("*************************"); 38 | //mybatis-plus版本2.0.9+ 39 | setFieldValByName("modifyTime", new Timestamp(System.currentTimeMillis()), metaObject); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/entity/Order.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.entity; 2 | 3 | import com.baomidou.mybatisplus.activerecord.Model; 4 | import com.baomidou.mybatisplus.annotations.TableField; 5 | import com.baomidou.mybatisplus.annotations.TableId; 6 | import com.baomidou.mybatisplus.annotations.TableName; 7 | import com.baomidou.mybatisplus.enums.IdType; 8 | import lombok.Data; 9 | 10 | import java.io.Serializable; 11 | import java.math.BigDecimal; 12 | import java.util.Date; 13 | 14 | /** 15 | *

16 | * 17 | *

18 | * 19 | * @author dgd123 20 | * @since 2018-02-10 21 | */ 22 | @Data 23 | @TableName("t_order") 24 | public class Order extends Model { 25 | 26 | private static final long serialVersionUID = 1L; 27 | 28 | @TableId(value = "id", type = IdType.AUTO) 29 | private Integer id; 30 | /** 31 | * 订单号 32 | */ 33 | @TableField("order_no") 34 | private String orderNo; 35 | /** 36 | * 用户ID 37 | */ 38 | @TableField("user_id") 39 | private Integer userId; 40 | /** 41 | * 支付金额 42 | */ 43 | private BigDecimal price; 44 | /** 45 | * 支付时间 46 | */ 47 | @TableField("paid_time") 48 | private Date paidTime; 49 | /** 50 | * 创建时间 51 | */ 52 | @TableField("create_time") 53 | private Date createTime; 54 | /** 55 | * 修改时间 56 | */ 57 | @TableField("modify_time") 58 | private Date modifyTime; 59 | 60 | @Override 61 | protected Serializable pkVal() { 62 | return this.id; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/warm/system/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.warm.system.controller; 2 | 3 | 4 | import com.warm.system.entity.Order; 5 | import com.warm.system.entity.User; 6 | import com.warm.system.service.db1.UserService; 7 | import com.warm.system.service.db2.OrderService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.math.BigDecimal; 14 | import java.util.List; 15 | 16 | /** 17 | *

18 | * 前端控制器 19 | *

20 | * 21 | * @author dgd123 22 | * @since 2018-02-10 23 | */ 24 | @RestController 25 | public class IndexController { 26 | @Autowired 27 | private UserService userService; 28 | @Autowired 29 | private OrderService orderService; 30 | 31 | @GetMapping("/user") 32 | public ResponseEntity> getUserList() { 33 | return ResponseEntity.ok(userService.getUserList()); 34 | } 35 | 36 | @GetMapping("/order") 37 | public ResponseEntity> getOrderList() { 38 | return ResponseEntity.ok(orderService.getOrderList()); 39 | } 40 | @GetMapping("/price") 41 | public ResponseEntity getPrice() { 42 | return ResponseEntity.ok(orderService.getOrderPriceByUserId(1)); 43 | } 44 | @GetMapping("/price2") 45 | public ResponseEntity getPrice2() { 46 | return ResponseEntity.ok(userService.getOrderPriceByUserId(1)); 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/com/warm/common/DataSourceSwitchAspect.java: -------------------------------------------------------------------------------- 1 | package com.warm.common; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.aspectj.lang.JoinPoint; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.aspectj.lang.annotation.Before; 7 | import org.aspectj.lang.annotation.Pointcut; 8 | import org.aspectj.lang.reflect.MethodSignature; 9 | import org.springframework.core.annotation.Order; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.Objects; 13 | 14 | /** 15 | * @Author DGD 16 | * @date 2018/2/7. 17 | */ 18 | 19 | @Component 20 | @Aspect 21 | @Order(-100) 22 | @Slf4j 23 | public class DataSourceSwitchAspect { 24 | 25 | @Pointcut("execution(* com.warm.system.service.db1..*.*(..))") 26 | private void db1Aspect() { 27 | } 28 | 29 | @Pointcut("execution(* com.warm.system.service.db2..*.*(..))") 30 | private void db2Aspect() { 31 | } 32 | 33 | @Before( "db1Aspect()" ) 34 | public void db1(JoinPoint joinPoint) { 35 | log.info("切换到db1 数据源..."); 36 | setDataSource(joinPoint,DBTypeEnum.db1); 37 | } 38 | 39 | @Before("db2Aspect()" ) 40 | public void db2 (JoinPoint joinPoint) { 41 | log.info("切换到db2 数据源..."); 42 | setDataSource(joinPoint,DBTypeEnum.db2); 43 | } 44 | 45 | /** 46 | * 添加注解方式,如果有注解优先注解,没有则按传过来的数据源配置 47 | * @param joinPoint 48 | * @param dbTypeEnum 49 | */ 50 | private void setDataSource(JoinPoint joinPoint, DBTypeEnum dbTypeEnum) { 51 | MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); 52 | DataSourceSwitch dataSourceSwitch = methodSignature.getMethod().getAnnotation(DataSourceSwitch.class); 53 | if (Objects.isNull(dataSourceSwitch) || Objects.isNull(dataSourceSwitch.value())) { 54 | DbContextHolder.setDbType(dbTypeEnum); 55 | }else{ 56 | log.info("根据注解来切换数据源,注解值为:"+dataSourceSwitch.value()); 57 | switch (dataSourceSwitch.value().getValue()) { 58 | case "db1": 59 | DbContextHolder.setDbType(DBTypeEnum.db1); 60 | break; 61 | case "db2": 62 | DbContextHolder.setDbType(DBTypeEnum.db2); 63 | break; 64 | default: 65 | DbContextHolder.setDbType(dbTypeEnum); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.warm 7 | dynamic-datasource 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | dynamic-datasource 12 | Demo project for dynamic datasource 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.10.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 1.0.4 27 | 2.1.8 28 | 1.1.3 29 | 1.16.14 30 | 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-web 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-aop 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-jdbc 50 | 51 | 52 | com.baomidou 53 | mybatisplus-spring-boot-starter 54 | ${mybatisplus-spring-boot-starter.version} 55 | 56 | 57 | com.baomidou 58 | mybatis-plus 59 | ${mybatisplus.version} 60 | 61 | 62 | 63 | 64 | com.alibaba 65 | druid 66 | ${druid.version} 67 | 68 | 69 | 70 | com.alibaba 71 | druid-spring-boot-starter 72 | ${druid.version} 73 | 74 | 75 | mysql 76 | mysql-connector-java 77 | runtime 78 | 79 | 80 | 81 | 82 | org.apache.velocity 83 | velocity 84 | 1.7 85 | 86 | 87 | 88 | 89 | org.projectlombok 90 | lombok 91 | ${lombok.version} 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | org.springframework.boot 101 | spring-boot-maven-plugin 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/main/java/com/warm/config/mybatis/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.warm.config.mybatis; 2 | 3 | import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; 4 | import com.baomidou.mybatisplus.MybatisConfiguration; 5 | import com.baomidou.mybatisplus.entity.GlobalConfiguration; 6 | import com.baomidou.mybatisplus.mapper.LogicSqlInjector; 7 | import com.baomidou.mybatisplus.plugins.PaginationInterceptor; 8 | import com.baomidou.mybatisplus.plugins.PerformanceInterceptor; 9 | import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean; 10 | import com.warm.common.DBTypeEnum; 11 | import com.warm.common.DynamicDataSource; 12 | import org.apache.ibatis.plugin.Interceptor; 13 | import org.apache.ibatis.session.SqlSessionFactory; 14 | import org.apache.ibatis.type.JdbcType; 15 | import org.mybatis.spring.annotation.MapperScan; 16 | import org.springframework.beans.factory.annotation.Qualifier; 17 | import org.springframework.boot.context.properties.ConfigurationProperties; 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.context.annotation.Primary; 21 | 22 | import javax.sql.DataSource; 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | 26 | /** 27 | * @Author DGD 28 | * @date 2018/2/6. 29 | */ 30 | @Configuration 31 | @MapperScan({"com.warm.system.mapper*"}) 32 | public class MybatisPlusConfig { 33 | 34 | /** 35 | * mybatis-plus分页插件
36 | * 文档:http://mp.baomidou.com
37 | */ 38 | @Bean 39 | public PaginationInterceptor paginationInterceptor() { 40 | PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); 41 | //paginationInterceptor.setLocalPage(true);// 开启 PageHelper 的支持 42 | return paginationInterceptor; 43 | } 44 | 45 | /** 46 | * mybatis-plus SQL执行效率插件【生产环境可以关闭】 47 | */ 48 | @Bean 49 | public PerformanceInterceptor performanceInterceptor() { 50 | return new PerformanceInterceptor(); 51 | } 52 | 53 | @Bean(name = "db1") 54 | @ConfigurationProperties(prefix = "spring.datasource.druid.db1" ) 55 | public DataSource db1 () { 56 | return DruidDataSourceBuilder.create().build(); 57 | } 58 | 59 | @Bean(name = "db2") 60 | @ConfigurationProperties(prefix = "spring.datasource.druid.db2" ) 61 | public DataSource db2 () { 62 | return DruidDataSourceBuilder.create().build(); 63 | } 64 | /** 65 | * 动态数据源配置 66 | * @return 67 | */ 68 | @Bean 69 | @Primary 70 | public DataSource multipleDataSource (@Qualifier("db1") DataSource db1, 71 | @Qualifier("db2") DataSource db2 ) { 72 | DynamicDataSource dynamicDataSource = new DynamicDataSource(); 73 | Map< Object, Object > targetDataSources = new HashMap<>(); 74 | targetDataSources.put(DBTypeEnum.db1.getValue(), db1 ); 75 | targetDataSources.put(DBTypeEnum.db2.getValue(), db2); 76 | dynamicDataSource.setTargetDataSources(targetDataSources); 77 | dynamicDataSource.setDefaultTargetDataSource(db1); 78 | return dynamicDataSource; 79 | } 80 | 81 | @Bean("sqlSessionFactory") 82 | public SqlSessionFactory sqlSessionFactory() throws Exception { 83 | MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean(); 84 | sqlSessionFactory.setDataSource(multipleDataSource(db1(),db2())); 85 | //sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*/*Mapper.xml")); 86 | 87 | MybatisConfiguration configuration = new MybatisConfiguration(); 88 | //configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class); 89 | configuration.setJdbcTypeForNull(JdbcType.NULL); 90 | configuration.setMapUnderscoreToCamelCase(true); 91 | configuration.setCacheEnabled(false); 92 | sqlSessionFactory.setConfiguration(configuration); 93 | sqlSessionFactory.setPlugins(new Interceptor[]{ //PerformanceInterceptor(),OptimisticLockerInterceptor() 94 | paginationInterceptor() 95 | }); 96 | sqlSessionFactory.setGlobalConfig(globalConfiguration()); 97 | return sqlSessionFactory.getObject(); 98 | } 99 | 100 | @Bean 101 | public GlobalConfiguration globalConfiguration() { 102 | GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector()); 103 | conf.setLogicDeleteValue("-1"); 104 | conf.setLogicNotDeleteValue("1"); 105 | conf.setIdType(0); 106 | conf.setMetaObjectHandler(new MyMetaObjectHandler()); 107 | conf.setDbColumnUnderline(true); 108 | conf.setRefresh(true); 109 | return conf; 110 | } 111 | 112 | 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/test/java/com/warm/generator/MpGenerator.java: -------------------------------------------------------------------------------- 1 | package com.warm.generator; 2 | 3 | import com.baomidou.mybatisplus.generator.AutoGenerator; 4 | import com.baomidou.mybatisplus.generator.InjectionConfig; 5 | import com.baomidou.mybatisplus.generator.config.*; 6 | import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert; 7 | import com.baomidou.mybatisplus.generator.config.po.TableInfo; 8 | import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; 9 | import com.baomidou.mybatisplus.generator.config.rules.DbType; 10 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; 11 | 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * @Author DGD 19 | * @date 2018/2/6. 20 | */ 21 | public class MpGenerator { 22 | /** 23 | * MySQL 生成演示 24 | * @param args 25 | */ 26 | public static void main(String[] args) { 27 | AutoGenerator mpg = new AutoGenerator(); 28 | 29 | // 全局配置 30 | GlobalConfig gc = new GlobalConfig(); 31 | gc.setOutputDir("F://generator/"); 32 | gc.setFileOverride(true);//是否覆盖已有文件 33 | gc.setActiveRecord(true);//开启 ActiveRecord 模式 34 | gc.setEnableCache(false);// XML 二级缓存 35 | gc.setBaseResultMap(true);// XML ResultMap 36 | gc.setBaseColumnList(false);// XML columList 37 | gc.setAuthor("dgd");//开发人员 38 | 39 | // 自定义文件命名,注意 %s 会自动填充表实体属性! 40 | // gc.setMapperName("%sDao"); 41 | // gc.setXmlName("%sDao"); 42 | gc.setServiceName("%sService"); 43 | // gc.setServiceImplName("%sServiceDiy"); 44 | // gc.setControllerName("%sAction"); 45 | mpg.setGlobalConfig(gc); 46 | 47 | // 数据源配置 48 | DataSourceConfig dsc = new DataSourceConfig(); 49 | dsc.setDbType(DbType.MYSQL); 50 | dsc.setTypeConvert(new MySqlTypeConvert(){ 51 | // 自定义数据库表字段类型转换【可选】 52 | @Override 53 | public DbColumnType processTypeConvert(String fieldType) { 54 | System.out.println("转换类型:" + fieldType); 55 | // 注意!!processTypeConvert 存在默认类型转换,如果不是你要的效果请自定义返回、非如下直接返回。 56 | return super.processTypeConvert(fieldType); 57 | } 58 | }); 59 | dsc.setDriverName("com.mysql.jdbc.Driver"); 60 | dsc.setUsername("root"); 61 | dsc.setPassword("root"); 62 | dsc.setUrl("jdbc:mysql://localhost:3306/db2?characterEncoding=utf8"); 63 | mpg.setDataSource(dsc); 64 | 65 | // 策略配置 66 | StrategyConfig strategy = new StrategyConfig(); 67 | // strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意 68 | //strategy.setTablePrefix(new String[] { "tlog_", "tsys_" });// 此处可以修改为您的表前缀 69 | strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略 70 | strategy.setInclude(new String[] { "user_role"}); // 需要生成的表 71 | // strategy.setExclude(new String[]{"test"}); // 排除生成的表 72 | // 自定义实体父类 73 | // strategy.setSuperEntityClass("com.baomidou.authentication.TestEntity"); 74 | // 自定义实体,公共字段 75 | // strategy.setSuperEntityColumns(new String[] { "test_id", "age" }); 76 | // 自定义 mapper 父类 77 | // strategy.setSuperMapperClass("com.baomidou.authentication.TestMapper"); 78 | // 自定义 service 父类 79 | // strategy.setSuperServiceClass("com.baomidou.authentication.TestService"); 80 | // 自定义 service 实现类父类 81 | // strategy.setSuperServiceImplClass("com.baomidou.authentication.TestServiceImpl"); 82 | // 自定义 controller 父类 83 | //strategy.setSuperControllerClass("com.jinhuatuo.common.base.BaseController"); 84 | // 【实体】是否生成字段常量(默认 false) 85 | // public static final String ID = "test_id"; 86 | // strategy.setEntityColumnConstant(true); 87 | // 【实体】是否为构建者模型(默认 false) 88 | // public User setName(String name) {this.name = name; return this;} 89 | // strategy.setEntityBuilderModel(true); 90 | mpg.setStrategy(strategy); 91 | 92 | // 包配置 93 | PackageConfig pc = new PackageConfig(); 94 | pc.setParent("com.warm.system"); 95 | pc.setController("controller"); 96 | //pc.setModuleName("test"); 97 | mpg.setPackageInfo(pc); 98 | 99 | // 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】 100 | InjectionConfig cfg = new InjectionConfig() { 101 | @Override 102 | public void initMap() { 103 | Map map = new HashMap(); 104 | map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-Mp"); 105 | this.setMap(map); 106 | } 107 | }; 108 | 109 | //输出文件配置 110 | List focList = new ArrayList(); 111 | /* 112 | // 自定义 xxList.jsp 生成 113 | focList.add(new FileOutConfig("/template/list.jsp.vm") { 114 | @Override 115 | public String outputFile(TableInfo tableInfo) { 116 | // 自定义输入文件名称 117 | return "D://my_" + tableInfo.getEntityName() + ".jsp"; 118 | } 119 | }); 120 | cfg.setFileOutConfigList(focList); 121 | mpg.setCfg(cfg); 122 | */ 123 | 124 | // 调整 xml 生成目录演示 125 | focList.add(new FileOutConfig("/templates/mapper.xml.vm") { 126 | @Override 127 | public String outputFile(TableInfo tableInfo) { 128 | return "/generator/" + tableInfo.getEntityName() + "Mapper.xml"; 129 | } 130 | }); 131 | cfg.setFileOutConfigList(focList); 132 | mpg.setCfg(cfg); 133 | 134 | // 关闭默认 xml 生成,调整生成 至 根目录 135 | TemplateConfig tc = new TemplateConfig(); 136 | tc.setXml(null); 137 | mpg.setTemplate(tc); 138 | 139 | // 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/template 下面内容修改, 140 | // 放置自己项目的 src/main/resources/template 目录下, 默认名称一下可以不配置,也可以自定义模板名称 141 | // TemplateConfig tc = new TemplateConfig(); 142 | // tc.setController("..."); 143 | // tc.setEntity("..."); 144 | // tc.setMapper("..."); 145 | // tc.setXml("..."); 146 | // tc.setService("..."); 147 | // tc.setServiceImpl("..."); 148 | // 如上任何一个模块如果设置 空 OR Null 将不生成该模块。 149 | // mpg.setTemplate(tc); 150 | 151 | // 执行生成 152 | mpg.execute(); 153 | 154 | // 打印注入设置【可无】 155 | System.err.println(mpg.getCfg().getMap().get("abc")); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | true 21 | 22 | 23 | [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n 24 | 25 | utf-8 26 | 27 | 28 | 29 | ${LOG_HOME}/${PROJECT_NAME}-%d{yyyy-MM-dd}.%i.log 30 | 31 | 50 MB 32 | 33 | 34 | 30 35 | 36 | 37 | 38 | 39 | true 40 | 41 | 42 | [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n 43 | 44 | utf-8 45 | 46 | 47 | 48 | ${LOG_HOME}/${PROJECT_NAME}-error-%d{yyyy-MM-dd}.%i.log 49 | 50 | 50 MB 51 | 52 | 53 | 30 54 | 55 | 56 | ERROR 57 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n 66 | 67 | 68 | 69 | 70 | 71 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | --------------------------------------------------------------------------------