前言
前幾個(gè)案例一直只有一個(gè)固定的數(shù)據(jù)源卵凑,但是實(shí)際開發(fā)中我們常常會(huì)有多個(gè)數(shù)據(jù)庫(kù)(分庫(kù)分表存放業(yè)務(wù)場(chǎng)景&主從場(chǎng)景)弄屡,所以本次來(lái)做個(gè)這樣的嘗試昼浦。
另外好唯,我們此次使用mybatis-plus插件來(lái)更方便的進(jìn)行數(shù)據(jù)操作。
幾個(gè)概念
多模塊(maven聚合):
我們之前的demo都是一個(gè)項(xiàng)目一個(gè)文件燥翅,但是實(shí)際生產(chǎn)場(chǎng)景中骑篙,這種方式還是比較少見的,正常一個(gè)項(xiàng)目都或或多或少的關(guān)聯(lián)另一個(gè)項(xiàng)目森书,比如開發(fā)了一套api項(xiàng)目靶端,這套api肯定會(huì)有對(duì)應(yīng)的web項(xiàng)目,app項(xiàng)目等等凛膏,那么如何在創(chuàng)建項(xiàng)目時(shí)就能體現(xiàn)這種依賴關(guān)系呢杨名?maven聚合應(yīng)運(yùn)而生。你可以簡(jiǎn)單的理解為有這么一個(gè)父項(xiàng)目猖毫,能管理所以依賴它的子項(xiàng)目台谍,當(dāng)父項(xiàng)目改動(dòng)編譯時(shí),對(duì)應(yīng)的所有子項(xiàng)目都會(huì)編譯重新打包
mybatis-plus:
MyBatis 是一款優(yōu)秀的持久層框架吁断,它支持定制化 SQL趁蕊、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis -plus則是在MyBatis 上的增強(qiáng)工具仔役,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變掷伙,為簡(jiǎn)化開發(fā)、提高效率而生又兵。
多數(shù)據(jù)源:
簡(jiǎn)而言之任柜,同時(shí)連接多個(gè)數(shù)據(jù)庫(kù)
項(xiàng)目構(gòu)建
博主使用的是IDEA開發(fā),所以建議大家都使用IDEA。
創(chuàng)建父項(xiàng)目
刪除src目錄宙地,因?yàn)楦疙?xiàng)目不寫代碼
創(chuàng)建子項(xiàng)目
右鍵選擇父項(xiàng)目
至此基本的項(xiàng)目結(jié)構(gòu)已經(jīng)建立摔认,但是實(shí)際上demo和web-api的"父子關(guān)系"還沒(méi)有建立,我們需要簡(jiǎn)單的修改下pom.xml
SpringBootDemo/pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<packaging>pom</packaging>
<modules>
<module>sbmp-multidb</module>
</modules>
sbmp-multidb/pom.xml更改parent:
<parent>
<groupId>com.mrcoder</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
Tips
那么問(wèn)題來(lái)了绸栅,既然所謂的依賴是加載包级野,那么若我們?cè)诟竝om.xml中加入一個(gè)依賴包,那么子模塊會(huì)自動(dòng)繼承這個(gè)依賴么粹胯?
這就引出了maven 關(guān)于pom依賴管理的知識(shí)蓖柔。請(qǐng)查看
9.1.從零開始學(xué)springboot-maven聚合下的pom依賴關(guān)系
添加依賴
以上完成了多模塊的配置,下面我們添加子模塊pom.xml依賴
完整依賴:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mrcoder</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.mrcoder</groupId>
<artifactId>sbmp-multidb</artifactId>
<version>0.0.1</version>
<name>sbmp-multidb</name>
<description>Demo project for Spring Boot</description>
<properties>
<spring.boot.version>2.1.0.RELEASE</spring.boot.version>
<mysql.version>8.0.12</mysql.version>
<mybatisplus.version>3.0.7.1</mybatisplus.version>
<dynamic-datasource.version>2.5.0</dynamic-datasource.version>
<lombok.version>1.18.2</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mysql驅(qū)動(dòng) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- lombok簡(jiǎn)化類 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>${lombok.version}</version>
</dependency>
<!-- 多數(shù)據(jù)源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic-datasource.version}</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<!-- mybatis-plus代碼生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
添加配置
application.yml:
spring:
datasource:
dynamic:
primary: db1 #設(shè)置默認(rèn)的數(shù)據(jù)源
datasource:
db1:
username: root
password: 123456
url: jdbc:mysql://192.168.145.131:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
db2:
username: root
password: 123456
url: jdbc:mysql://192.168.145.131:3306/test2?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.Driver
mp-enabled: true
logging:
level:
com.xkcoding.multi.datasource.mybatis: debug
建庫(kù)
建立test风纠、test2數(shù)據(jù)庫(kù)
test庫(kù)建表:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for multi_user
-- ----------------------------
DROP TABLE IF EXISTS `multi_user`;
CREATE TABLE `multi_user` (
`id` bigint(64) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`age` int(30) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of multi_user
-- ----------------------------
INSERT INTO `multi_user` VALUES ('1', '主庫(kù)添加222', '20');
test2庫(kù)建表:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for multi_user
-- ----------------------------
DROP TABLE IF EXISTS `multi_user`;
CREATE TABLE `multi_user` (
`id` bigint(64) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`age` int(30) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of multi_user
-- ----------------------------
INSERT INTO `multi_user` VALUES ('1103566261448732674', '主庫(kù)添加', '20');
INSERT INTO `multi_user` VALUES ('1103566303475658753', '主庫(kù)添加', '20');
INSERT INTO `multi_user` VALUES ('1103566435235524610', '主庫(kù)添加', '20');
mybatis-plus代碼生成器的使用
以上我們成功創(chuàng)建了一個(gè)多模塊的項(xiàng)目况鸣,父項(xiàng)目為SpringBootDemo,子項(xiàng)目為sbmp-multidb
接下來(lái)竹观,我們完善各"層"代碼镐捧,考慮到手動(dòng)一個(gè)個(gè)創(chuàng)建類文件和包太麻煩,這邊我們使用一個(gè)偷懶工具臭增,mybatis-plus-generator來(lái)自動(dòng)生成相關(guān)的包和類文件(和mubatis-generator類似的功能)懂酱。
我們先右鍵新增一個(gè)名叫g(shù)enerator的package,里面新增一個(gè)MysqlGenerator的類文件誊抛,
generator/MysqlGenerator:
package com.mrcoder.sbmpmultidb.generator;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* <p>
* mysql 代碼生成器演示例子
* </p>
*/
public class MysqlGenerator {
/**
* <p>
* 讀取控制臺(tái)內(nèi)容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("請(qǐng)輸入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("請(qǐng)輸入正確的" + tip + "列牺!");
}
/**
* RUN THIS
*/
public static void main(String[] args) {
// 代碼生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/sbmp-multidb/src/main/java");
gc.setAuthor("mrcoder");
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 數(shù)據(jù)源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://192.168.145.131:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("模塊名"));
pc.setParent("com.mrcoder");
mpg.setPackageInfo(pc);
// 自定義配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定義輸入文件名稱
return projectPath + "/sbmp-multidb/src/main/resources/mapper/" + pc.getModuleName()
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//strategy.setSuperEntityClass("com.mrcoder.sbmpmultidb.BaseEntity");
strategy.setEntityLombokModel(true);
//strategy.setSuperControllerClass("com.mrcoder.sbmpmultidb.BaseController");
strategy.setInclude(scanner("表名"));
strategy.setSuperEntityColumns("id");
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
// 選擇 freemarker 引擎需要指定如下加,注意 pom 依賴必須有拗窃!
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
相關(guān)的注釋已經(jīng)加上了瞎领,自行閱讀,或者直接去看官方文檔~随夸,根據(jù)實(shí)際情況酌情修改九默。
這邊我們直接運(yùn)行代碼生成器,點(diǎn)擊綠色的小箭頭
運(yùn)行時(shí)會(huì)讓你填寫模塊名和數(shù)據(jù)表名宾毒,
模塊名寫子模塊的名稱即可驼修,這邊不寫子模塊名填寫其它名字的話則會(huì)自動(dòng)創(chuàng)建一個(gè)子模塊并將文件生成進(jìn)去。
數(shù)據(jù)表名如實(shí)填寫即可
目錄結(jié)構(gòu)
如圖伍俘,標(biāo)紅部分為代碼生成器自動(dòng)生成的代碼邪锌,只需小小的完善即可使用。
controller和service/impl還是需要手動(dòng)創(chuàng)建的癌瘾。
完善
我們創(chuàng)建controller和service/impl的package觅丰,補(bǔ)充代碼
controller/MultiUserController:
package com.mrcoder.sbmpmultidb.controller;
import com.mrcoder.sbmpmultidb.entity.MultiUser;
import com.mrcoder.sbmpmultidb.service.IMultiUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author mrcoder
* @since 2019-03-07
*/
@Controller
@RestController
@RequestMapping("/sbmpmultidb/multi-user")
public class MultiUserController {
@Autowired
private IMultiUserService userService;
@RequestMapping("/id")
public MultiUser id(){
MultiUser user = userService.getById(1);
return user;
}
@RequestMapping("/list")
public List<MultiUser> list() {
List<MultiUser> userList = userService.list();
return userList;
}
@RequestMapping("add")
public String add(){
MultiUser userMaster = MultiUser.builder().name("主庫(kù)添加").age(20).build();
userService.addUser(userMaster);
return "add success";
}
@RequestMapping("update")
public String update(){
MultiUser userMaster = MultiUser.builder().id(1L).name("主庫(kù)添加222").age(20).build();
userService.updateById(userMaster);
return "update success";
}
}
entity/MultiUser:
package com.mrcoder.sbmpmultidb.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author mrcoder
* @since 2019-02-26
*/
@Data
@TableName("multi_user")
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MultiUser implements Serializable {
private static final long serialVersionUID = -1923859222295750467L;
//private static final long serialVersionUID = 1L;
@TableId(type = IdType.ID_WORKER)
private Long id;
private String name;
private Integer age;
}
mapper/MultiUserMapper:
package com.mrcoder.sbmpmultidb.mapper;
import com.mrcoder.sbmpmultidb.entity.MultiUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author mrcoder
* @since 2019-03-07
*/
public interface MultiUserMapper extends BaseMapper<MultiUser> {
}
service/IMultiUserService:
package com.mrcoder.sbmpmultidb.service;
import com.mrcoder.sbmpmultidb.entity.MultiUser;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服務(wù)類
* </p>
*
* @author mrcoder
* @since 2019-03-07
*/
public interface IMultiUserService extends IService<MultiUser> {
void addUser(MultiUser user);
}
service/impl/MultiUserServiceImpl:
package com.mrcoder.sbmpmultidb.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.mrcoder.sbmpmultidb.entity.MultiUser;
import com.mrcoder.sbmpmultidb.mapper.MultiUserMapper;
import com.mrcoder.sbmpmultidb.service.IMultiUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服務(wù)實(shí)現(xiàn)類
* </p>
*
* @author mrcoder
* @since 2019-03-07
*/
@Service
@DS("db1")
public class MultiUserServiceImpl extends ServiceImpl<MultiUserMapper, MultiUser> implements IMultiUserService {
@DS("db2")
@Override
public void addUser(MultiUser user) {
baseMapper.insert(user);
}
}
最后我們?cè)谌肟谖募屑尤霋呙璨僮?
SbmpMultidbApplication:
package com.mrcoder.sbmpmultidb;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.mrcoder.sbmpmultidb.mapper")
public class SbmpMultidbApplication {
public static void main(String[] args) {
SpringApplication.run(SbmpMultidbApplication.class, args);
}
}
運(yùn)行
項(xiàng)目地址
https://github.com/MrCoderStack/SpringBootDemo/tree/master/sbmp-multidb
https://gitee.com/MrCoderStack/SpringBootDemo/tree/master/sbmp-multidb