├── 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 |
--------------------------------------------------------------------------------