spring-cloud集成mybatis-plus
mybatis-plus插件是对mybatis做出系列增强插件,后面简称mp,mp可免去开发者重复编写xml、mapper、service、entity等代码,通过mp提供的实体注解来完成单表的crud简单操作,mp同样配套有代码生成工具,可通过简单的配置来生成xml、mapper、service、entity等文件,极大提升了开发速度,本文是在spring-cloud的环境下集成mybatis-plus。
spirng-cloud的基础环境搭建可参考。
进入正文。
——————————————————————————————————————————————————————————————————————————————————————————————————————————————
先来pom.xml文件
<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> <groupid>custom-authorize</groupid> <artifactid>custom-authorize</artifactid> <version>0.0.1-snapshot</version> <!-- 引入spring boot的依赖 --> <parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.0.7.release</version> </parent> <properties> <project.build.sourceencoding>utf-8</project.build.sourceencoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- junit的spring-boot依赖 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency> <!-- alibaba fastjson 格式化对 --> <dependency> <groupid>com.alibaba</groupid> <artifactid>fastjson</artifactid> <version>1.1.41</version> </dependency> <!-- feign组件依赖 --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-openfeign</artifactid> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> <!-- jwt认证协议依赖 --> <dependency> <groupid>io.jsonwebtoken</groupid> <artifactid>jjwt</artifactid> <version>0.9.0</version> </dependency> <!-- redis依赖 --> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-data-redis</artifactid> </dependency> <dependency> <groupid>org.apache.commons</groupid> <artifactid>commons-pool2</artifactid> </dependency> <!-- eureka服务组件 --> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-starter-netflix-eureka-client</artifactid> </dependency> <!-- mysql --> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> </dependency> <!-- mybatis依赖 --> <!-- <dependency> <groupid>org.mybatis.spring.boot</groupid> <artifactid>mybatis-spring-boot-starter</artifactid> <version>1.3.1</version> </dependency> --> <dependency> <groupid>com.baomidou</groupid> <artifactid>mybatis-plus-boot-starter</artifactid> <version>3.0-gamma</version> </dependency> <!-- 引入lombok --> <dependency> <groupid>org.projectlombok</groupid> <artifactid>lombok</artifactid> <optional>true</optional> </dependency> <!-- mybatis-plus代码生成器模板引擎 --> <dependency> <groupid>org.freemarker</groupid> <artifactid>freemarker</artifactid> </dependency> </dependencies> <!-- 引入spring cloud的依赖,不能少,主要用来管理spring cloud生态各组件的版本 --> <dependencymanagement> <dependencies> <dependency> <groupid>org.springframework.cloud</groupid> <artifactid>spring-cloud-dependencies</artifactid> <version>finchley.sr2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencymanagement> <!-- 添加spring-boot的maven插件,不能少,打jar包时得用 --> <build> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> </plugins> </build> </project>
里面部分jar包是微服务所需jar包,核心jar包commons-pool2、mysql-connector-java、mybatis-plus-boot-starter、lombok、freemarker、spring-cloud、spring-boot这几个,其他的不需要可以删掉。
lombok可以极大减少实体重复代码的编写,例如get/set/tostring/constrator等,感兴趣的朋友可以去度娘一下,基本就是几个注解。
这里使用的是3.x版本的mp插件,支持jdk1.8的特性,文档地址:。
再来编写入口类:
package com.authorize; import org.mybatis.spring.annotation.mapperscan; import org.springframework.boot.springapplication; import org.springframework.boot.autoconfigure.springbootapplication; import org.springframework.cloud.netflix.eureka.enableeurekaclient; import org.springframework.cloud.openfeign.enablefeignclients; import org.springframework.context.annotation.bean; import com.baomidou.mybatisplus.extension.plugins.paginationinterceptor; /** * 入口类 * @title authorizeapplication.java * @package com.authorize * @description todo(一句话描述该类作用) * @author pandong * @date 2019年2月22日 */ @springbootapplication @enablefeignclients // 服务之间通信所需注解 @enableeurekaclient // 基于spring-boot环境的可以删掉上面及本行注解 @mapperscan("com.authorize.dao") public class authorizeapplication { public static void main(string[] args) { springapplication.run(authorizeapplication.class, args); } /** * mp分页插件,后面会有说明 */ @bean public paginationinterceptor paginationinterceptor() { return new paginationinterceptor(); } }
编写application.yml文件:
server: port: 8082 spring: application: # 指定注册到eureka server上的服务名称 name: custom-authorize #################################redis配置######################################## redis: host: 127.0.0.1 password: 123 port: 6379 timeout: 10000 # 连接超时时间(毫秒) database: 0 # redis默认情况下有16个分片,这里配置具体使用的分片,默认是0 lettuce: pool: max-active: 8 # 连接池最大连接数(使用负值表示没有限制)默认 8 max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)默认 -1 max-idle: 8 # 连接池中的最大空闲连接默认 8 min-idle: 0 # 连接池中的最小空闲连接默认 0 #################################redis配置######################################## ##################################################################################################### # mysql 属性配置 datasource: driver-class-name: com.mysql.jdbc.driver url: jdbc:mysql://127.0.0.1:3306/web_custom username: root password: pd123 # jpa: # hibernate: # #ddl-auto: create #ddl-auto:设为create表示每次都重新建表 # ddl-auto: update #ddl-auto:设为update表示每次都不会重新建表 # show-sql: true ##################################################################################################### ##################################################################################################### # mybatis mapper xml 配置 #mybatis: # mybatis.type-aliases-package:指定domain类的基包,即指定其在*mapper.xml文件中可以使用简名来代替全类名(看后边的usermapper.xml介绍) #type-aliases-package: #mapper-locations: classpath:mybatis/mapper/*.xml #config-location: classpath:mybatis/mybatis-config.xml # mybatis-plus 配置 mybatis-plus: # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*mapper.xml # 如果是放在resource目录 classpath:/mapper/*mapper.xml config-location: classpath:/mybatis/mybatis-config.xml mapper-locations: classpath:/mybatis/mapper/*.xml #实体扫描,多个package用逗号或者分号分隔 typealiasespackage: com.authorize.entity global-config: #主键类型 0:"数据库id自增", 1:"用户输入id",2:"全局唯一id (数字类型唯一id)", 3:"全局唯一id uuid"; id-type: 3 # 热加载mapper文件 refresh: true db-config: db-type: mysql ##################################################################################################### eureka: client: service-url: # 指定eureka server通信地址,注意/eureka/小尾巴不能少 defaultzone: http://admin:123@localhost:8080/eureka/ instance: # 是否注册ip到eureka server,如不指定或设为false,那就会注册主机名到eureka server prefer-ip-address: true logging: level: root: info org.hibernate: info org.hibernate.type.descriptor.sql.basicbinder: trace org.hibernate.type.descriptor.sql.basicextractor: trace com.authorize: debug
编写mybatis-config.xml文件:
<?xml version="1.0" encoding="utf-8" ?> <!doctype configuration public "-//mybatis.org//dtd config 3.0//en" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="callsettersonnulls" value="true"/> <setting name="cacheenabled" value="true"/> <setting name="lazyloadingenabled" value="true"/> <setting name="aggressivelazyloading" value="true"/> <setting name="multipleresultsetsenabled" value="true"/> <setting name="usecolumnlabel" value="true"/> <setting name="usegeneratedkeys" value="false"/> <setting name="automappingbehavior" value="partial"/> <setting name="defaultexecutortype" value="simple"/> <setting name="mapunderscoretocamelcase" value="true"/> <setting name="localcachescope" value="session"/> <setting name="jdbctypefornull" value="null"/> </settings> <typealiases> <typealias alias="integer" type="java.lang.integer" /> <typealias alias="long" type="java.lang.long" /> <typealias alias="hashmap" type="java.util.hashmap" /> <typealias alias="linkedhashmap" type="java.util.linkedhashmap" /> <typealias alias="arraylist" type="java.util.arraylist" /> <typealias alias="linkedlist" type="java.util.linkedlist" /> </typealiases> </configuration>
编写实体类:
1 package com.authorize.entity; 2 3 import java.math.bigdecimal; 4 import com.baomidou.mybatisplus.annotation.tablename; 5 import com.baomidou.mybatisplus.annotation.idtype; 6 import com.baomidou.mybatisplus.extension.activerecord.model; 7 import com.baomidou.mybatisplus.annotation.tableid; 8 import com.baomidou.mybatisplus.annotation.tablefield; 9 import java.io.serializable; 10 11 import lombok.data; 12 import lombok.equalsandhashcode; 13 import lombok.experimental.accessors; 14 15 /** 16 * <p> 17 * 18 * </p> 19 * 20 * @author pandong 21 * @since 2019-03-05 22 */ 23 @data 24 @equalsandhashcode(callsuper = false) 25 @accessors(chain = true) 26 @tablename("ct_user") 27 public class ctuser extends model<ctuser> { 28 29 private static final long serialversionuid = 1l; 30 31 /** 32 * 主键 33 */ 34 @tableid(value = "user_id", type = idtype.auto) 35 private long userid; 36 37 /** 38 * 用户名称 39 */ 40 @tablefield("user_name") 41 private string username; 42 43 /** 44 * 年龄 45 */ 46 private integer age; 47 48 /** 49 * 价格 50 */ 51 private bigdecimal balance; 52 53 54 @override 55 protected serializable pkval() { 56 return this.userid; 57 } 58 59 }
可以看到实体类上面使用了与hibernate相似的注解,属性上面使用了tableid注解,属性还有其他注解,可自行去查看文档。
实体上其他注解都是lombok的注解,是不是减少了很多代码。
编写mapper:
package com.authorize.dao; import com.authorize.entity.ctuser; import com.baomidou.mybatisplus.core.mapper.basemapper; /** * <p> * mapper 接口 * </p> * * @author pandong * @since 2019-03-05 */ public interface ctusermapper extends basemapper<ctuser> { }
没看错,只需要继承basemapper就可实现crud,里面有大量的基础方法提供调用,能满足大部分的单表以及分页操作。
mapper上面未使用@mapper注解,是因为在入口类中增加了注解@mapperscan注解。
编写service:
package com.authorize.service.authorize; import com.authorize.entity.ctuser; import com.baomidou.mybatisplus.extension.service.iservice; /** * <p> * 服务类 * </p> * * @author pandong * @since 2019-03-05 */ public interface ictuserservice extends iservice<ctuser> { }
编写impl:
package com.authorize.service.impl; import com.authorize.entity.ctuser; import com.authorize.dao.ctusermapper; import com.authorize.service.authorize.ictuserservice; import com.baomidou.mybatisplus.extension.service.impl.serviceimpl; import org.springframework.stereotype.service; /** * <p> * 服务实现类 * </p> * * @author pandong * @since 2019-03-05 */ @service public class ctuserserviceimpl extends serviceimpl<ctusermapper, ctuser> implements ictuserservice { }
service同样继承mp提供的*基类,里面包含了大量的基础方法提供调用。
编写完成后整体的目录结构:
generatortemplate目录是代码生成的自定义模板目录,后面说代码生成会说到。
最后编写测试类:
package com.authorize.controller; import static org.springframework.test.web.servlet.result.mockmvcresultmatchers.status; import org.junit.before; import org.junit.test; import org.junit.runner.runwith; import org.springframework.beans.factory.annotation.autowired; import org.springframework.boot.test.context.springboottest; import org.springframework.http.mediatype; import org.springframework.test.context.junit4.springjunit4classrunner; import org.springframework.test.web.servlet.mockmvc; import org.springframework.test.web.servlet.resultactions; import org.springframework.test.web.servlet.request.mockmvcrequestbuilders; import com.authorize.authorizeapplication; import com.authorize.service.authorize.ictmenuservice; /** * * @filename ctsysysercontrollertest.java * @pakage com.authorize.controller * @descption todo(用一句话表述类的作用) * @author pandong * @date 2019年3月5日 */ @runwith(springjunit4classrunner.class) @springboottest(classes = authorizeapplication.class) public class ctsysysercontrollertest { @autowired private ictuserservice ss;
// 由于我数据库中已经有数据,所以插入数据的代码就不写了 @test public void test() { ctuser ctuser = ss.selectbyid(1); system.out.println(user); } }
到这里mp已经集成进来了,单表基本不用自己去写任何代码,当然,上面只是基本的配置,现在来说分页插件如何使用。
官方文档中有多个分页的实现,这里只讲官方推荐的方式,在上面的入口类中已经添加了分页插件的初始化(使用spring同志请自行去看文档)。
@bean public paginationinterceptor paginationinterceptor() { return new paginationinterceptor(); }
编写测试类:
package com.authorize.controller; import org.junit.test; import org.junit.runner.runwith; import org.springframework.beans.factory.annotation.autowired; import org.springframework.boot.test.context.springboottest; import org.springframework.test.context.junit4.springjunit4classrunner; import com.authorize.authorizeapplication; import com.authorize.entity.ctuser; import com.authorize.service.authorize.ictuserservice; import com.baomidou.mybatisplus.core.conditions.query.querywrapper; import com.baomidou.mybatisplus.core.metadata.ipage; import com.baomidou.mybatisplus.extension.plugins.pagination.page; /** * * @filename ctsysysercontrollertest.java * @pakage com.authorize.controller * @descption todo(用一句话表述类的作用) * @author pandong * @date 2019年3月5日 */ @runwith(springjunit4classrunner.class) @springboottest(classes = authorizeapplication.class) public class ctusercontrollertest { @autowired private ictuserservice ss; @test public void test() { ipage<ctuser> page = new page<>(1, 20); querywrapper<ctuser> wapper = new querywrapper<>(); page = ss.selectpage(page, wapper); system.out.println(page.getrecords()); } }
mp实现分页只需要new page就完了,这样就完成一个简单的分页查询。
可能有的朋友看不明白querywrapper是什么,querywrapper是mp对查询的封装,这里做一些简单的说明,详细的去文档中查看,国人大牛开发的,注释都是中文的。
@test public void test1() { ipage<ctuser> page = new page<>(1, 20); querywrapper<ctuser> wapper = new querywrapper<>(); lambdaquerywrapper<ctuser> lambda = wapper.lambda(); lambda.and( obj -> obj.eq(ctuser::getusername, "张三").eq(ctuser::getage, "30")); page = ss.selectpage(page, lambda); system.out.println(page.getrecords()); }
上面代码是一个简单的查询分页操作,mp支持lambda表达式以及1.8的一些新特性,看不明白函数接口、方法引用的可参考。
lambdaquerywrapper中封装了很多方法来构造各种不同的查询条件,上面所用到的and方法,查询的sql语句:select user_id as userid,user_name as username,age,balance from ct_user where ( user_name = ? and age = ? ) ,
里面还封装了eq、or、like等等,详细的可以去看官方文档,上文中就给出地址。
到这里mp基本的curd已经算是完成了,最后再来说一下代码生成:
package com.authorize.utils.generator; import java.util.arraylist; import java.util.hashmap; import java.util.list; import java.util.map; import com.baomidou.mybatisplus.annotation.dbtype; import com.baomidou.mybatisplus.generator.autogenerator; import com.baomidou.mybatisplus.generator.injectionconfig; import com.baomidou.mybatisplus.generator.config.datasourceconfig; import com.baomidou.mybatisplus.generator.config.fileoutconfig; import com.baomidou.mybatisplus.generator.config.globalconfig; import com.baomidou.mybatisplus.generator.config.packageconfig; import com.baomidou.mybatisplus.generator.config.strategyconfig; import com.baomidou.mybatisplus.generator.config.converts.mysqltypeconvert; import com.baomidou.mybatisplus.generator.config.po.tableinfo; import com.baomidou.mybatisplus.generator.config.rules.dbcolumntype; import com.baomidou.mybatisplus.generator.config.rules.namingstrategy; import com.baomidou.mybatisplus.generator.engine.freemarkertemplateengine; /** * 基于mybatis-plus的代码成功工具 * * @filename entitygenerator.java * @pakage com.authorize.utils.generator * @descption todo(用一句话表述类的作用) * @author pandong * @date 2019年3月1日 */ public class entitygenerator { public static void main(string[] args) { generator(); } public static void generator() { autogenerator mpg = new autogenerator(); // 选择 freemarker 引擎,默认 veloctiy mpg.settemplateengine(new freemarkertemplateengine()); // 全局配置 globalconfig gc = new globalconfig(); gc.setauthor("pandong"); gc.setoutputdir("d:\\workspace\\springcloud_learning\\custom-authorize\\src\\main\\java"); gc.setfileoverride(false);// 是否覆盖同名文件,默认是false gc.setactiverecord(true);// 不需要activerecord特性的请改为false gc.setenablecache(false);// xml 二级缓存 gc.setbaseresultmap(true);// xml resultmap gc.setbasecolumnlist(false);// xml columlist /* 自定义文件命名,注意 %s 会自动填充表实体属性! */ // gc.setmappername("%sdao"); // gc.setxmlname("%sdao"); // gc.setservicename("mp%sservice"); // gc.setserviceimplname("%sservicediy"); // gc.setcontrollername("%saction"); mpg.setglobalconfig(gc); // 数据源配置 datasourceconfig dsc = new datasourceconfig(); dsc.setdbtype(dbtype.mysql); dsc.settypeconvert(new mysqltypeconvert() { // 自定义数据库表字段类型转换【可选】 public dbcolumntype processtypeconvert(string fieldtype) { system.out.println("转换类型:" + fieldtype); // 注意!!processtypeconvert 存在默认类型转换,如果不是你要的效果请自定义返回、非如下直接返回。 return super.processtypeconvert(gc, fieldtype); } }); dsc.setdrivername("com.mysql.jdbc.driver"); dsc.setusername("root"); dsc.setpassword("pd123"); dsc.seturl("jdbc:mysql://localhost:3306/web_custom?useunicode=true&characterencoding=utf8"); mpg.setdatasource(dsc); // 策略配置 strategyconfig strategy = new strategyconfig(); // strategy.setcapitalmode(true);// 全局大写命名 oracle 注意 // strategy.settableprefix(new string[] { "ct_" });// 此处可以修改为您的表前缀 strategy.setnaming(namingstrategy.underline_to_camel);// 表名生成策略 strategy.setinclude(new string[] { "ct_authorize","ct_btn","ct_menu","ct_role","ct_sysuser","ct_user"}); // 需要生成的表 strategy.setentitylombokmodel(true); // 生成lombox模型实体 strategy.entitytablefieldannotationenable(true); // // strategy.setexclude(new string[]{"test"}); // 排除生成的表 // 自定义实体父类 // strategy.setsuperentityclass("com.baomidou.demo.testentity"); // 自定义实体,公共字段 // strategy.setsuperentitycolumns(new string[] { "test_id", "age" }); // 自定义 mapper 父类 // strategy.setsupermapperclass("com.baomidou.demo.testmapper"); // 自定义 service 父类 // strategy.setsuperserviceclass("com.authorize.service.authorize.idgeneratorservice"); // 自定义 service 实现类父类 // strategy.setsuperserviceimplclass("com.authorize.service.impl.idgeneratorserviceimpl"); // 自定义 controller 父类 strategy.setsupercontrollerclass("com.authorize.controller.basecontroller"); // 【实体】是否生成字段常量(默认 false) // public static final string id = "test_id"; // strategy.setentitycolumnconstant(true); // 【实体】是否为构建者模型(默认 false) // public user setname(string name) {this.name = name; return this;} // strategy.setentitybuildermodel(true); mpg.setstrategy(strategy); // 包配置 packageconfig pc = new packageconfig(); pc.setparent("com.authorize"); pc.setservice("service.authorize"); pc.setserviceimpl("service.impl"); pc.setxml(null); pc.setmapper("dao"); // pc.setmodulename("test"); mpg.setpackageinfo(pc); // 注入自定义配置,可以在 vm 中使用 cfg.abc 【可无】 injectionconfig cfg = new injectionconfig() { @override public void initmap() { } }; // // // 自定义 xxlist.jsp 生成 list<fileoutconfig> foclist = new arraylist<>(); // foclist.add(new fileoutconfig("/template/list.jsp.vm") { // @override // public string outputfile(tableinfo tableinfo) { // // 自定义输入文件名称 // return "d://my_" + tableinfo.getentityname() + ".jsp"; // } // }); // cfg.setfileoutconfiglist(foclist); // mpg.setcfg(cfg); // // // 调整 xml 生成目录演示 foclist.add(new fileoutconfig("/mybatis/generatortemplate/mapper.xml.ftl") { @override public string outputfile(tableinfo tableinfo) { return "src/main/resources/mybatis/mapper/" + tableinfo.getentityname() + "mapper.xml"; } }); cfg.setfileoutconfiglist(foclist); mpg.setcfg(cfg); // // // 关闭默认 xml 生成,调整生成 至 根目录 // templateconfig tc = new templateconfig(); // tc.setxml(null); // mpg.settemplate(tc); // 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改, // 放置自己项目的 src/main/resources/templates 目录下, 默认名称一下可以不配置,也可以自定义模板名称 // templateconfig tc = new templateconfig(); // tc.setcontroller("..."); // tc.setentity("..."); // tc.setmapper("..."); // tc.setxml("..."); // tc.setservice("..."); // tc.setserviceimpl("..."); // 如上任何一个模块如果设置 空 or null 将不生成该模块。 // mpg.settemplate(tc); // 执行生成 mpg.execute(); // 打印注入设置【可无】 // system.err.println(mpg.getcfg().getmap().get("abc")); } }
上面是官网给出的例子改的demo,上面我自己改了代码生成的位置,使用的模板也改过了,模板可以从源码的templates中拷贝。
这里配置生成文件的位置,可自行修改位置。
这段代码就是修改xml生成的位置,以及使用自己修改过的模板。
说到这里基本集成已经完成了,包含了生成的系列代码,更详细的就去看官方文档。。。
上一篇: 要不要这么用功
下一篇: layui-时间选择器-时间范围选择
推荐阅读
-
iOS8中如何集成TouchID指纹传感器功能
-
Android 集成 google 登录并获取性别等隐私信息的实现代码
-
springcloud学习之路: (四) springcloud集成Hystrix服务保护
-
asp.net core集成JWT的步骤记录
-
多模块maven的deploy集成gitlab ci自动发版配置
-
使用Spring Boot集成FastDFS的示例代码
-
Spring Boot与Spark、Cassandra系统集成开发示例
-
centos下GitLab+Jenkins持续集成环境搭建(安装jenkins)
-
华为官宣麒麟990:9月6日德国IFA发布、集成达芬奇架构新NPU
-
ABP 结合 MongoDB 集成依赖注入