·本篇:3.4k字 大约需要: 16分钟
MyBatis Generator
MyBatis Generator(简称MBG)是MyBatis官方提供的代码生成工具,可以通过数据库表直接生成实体类、单表CRUD代码、mapper.xml文件
SpringBoot继承MBG
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.1.3</version > </dependency > <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper-spring-boot-starter</artifactId > <version > 1.4.2</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid-spring-boot-starter</artifactId > <version > 1.1.10</version > </dependency > <dependency > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-core</artifactId > <version > 1.4.0</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.15</version > </dependency > <dependency > <groupId > io.springfox</groupId > <artifactId > springfox-swagger2</artifactId > <version > 2.7.0</version > </dependency > <dependency > <groupId > io.springfox</groupId > <artifactId > springfox-swagger-ui</artifactId > <version > 2.7.0</version > </dependency >
在application.yml
中对数据源和MyBatis
的mapper.xml
文件路径进行配置,这里进行约定,MBG生成的xml
文件放在resources/com/**/mapper
目录下,自定义的xml
文件放在resources/mapper
目录下
1 2 3 4 5 mybatis: mapper-locations: - classpath:mapper/*.xml - classpath*:com/**/mapper/*.xml
添加Java
配置,用于扫描Mapper
接口路径,这里进行约定,MBG生成的放在com.**.mbg.mapper
包下,自定义的放在com.**.mapper
包下
1 2 3 @Configuration @MapperScan({"com.t1k.mall.mbg.mapper", "com.t1k.mall.mapper"}) public class MyBatisConfig {}
使用代码生成器
在使用MBG生成代码前,还需要对其进行一些配置,首先在generator.properties
文件中配置好数据库连接信息
1 2 3 4 jdbc.driverClass =com.mysql.cj.jdbc.Driver jdbc.connectionURL =jdbc:mysql://localhost:3306/mall-test-1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai jdbc.userId =root jdbc.password =123
然后在generatorConfig.xml
文件中对MBG进行配置,配置属性说明直接参考注释即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration > <properties resource ="generator.properties" /> <context id ="MySqlContext" targetRuntime ="MyBatis3" defaultModelType ="flat" > <property name ="beginningDelimiter" value ="`" /> <property name ="endingDelimiter" value ="`" /> <property name ="javaFileEncoding" value ="UTF-8" /> <plugin type ="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" /> <plugin type ="org.mybatis.generator.plugins.SerializablePlugin" /> <plugin type ="org.mybatis.generator.plugins.ToStringPlugin" /> <commentGenerator type ="com.t1k.mall.mbg.CommentGenerator" > <property name ="suppressAllComments" value ="true" /> <property name ="suppressDate" value ="true" /> <property name ="addRemarkComments" value ="true" /> </commentGenerator > <jdbcConnection driverClass ="${jdbc.driverClass}" connectionURL ="${jdbc.connectionURL}" userId ="${jdbc.userId}" password ="${jdbc.password}" > <property name ="nullCatalogMeansCurrent" value ="true" /> </jdbcConnection > <javaModelGenerator targetPackage ="com.t1k.mall.mbg.model" targetProject ="mall-test-mbg\src\main\java" /> <sqlMapGenerator targetPackage ="com.t1k.mall.mbg.mapper" targetProject ="mall-test-mbg\src\main\resources" /> <javaClientGenerator type ="XMLMAPPER" targetPackage ="com.t1k.mall.mbg.mapper" targetProject ="mall-test-mbg\src\main\java" /> <table tableName ="ums_admin" > <generatedKey column ="id" sqlStatement ="MySql" identity ="true" /> </table > <table tableName ="ums_role" > <generatedKey column ="id" sqlStatement ="MySql" identity ="true" /> </table > <table tableName ="ums_admin_role_relation" > <generatedKey column ="id" sqlStatement ="MySql" identity ="true" /> </table > <table tableName ="ums_resource" > <generatedKey column ="id" sqlStatement ="MySql" identity ="true" /> </table > <table tableName ="ums_resource_category" > <generatedKey column ="id" sqlStatement ="MySql" identity ="true" /> </table > </context > </generatorConfiguration >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 package com.t1k.mall.mbg;import org.mybatis.generator.api.IntrospectedColumn;import org.mybatis.generator.api.IntrospectedTable;import org.mybatis.generator.api.dom.java.CompilationUnit;import org.mybatis.generator.api.dom.java.Field;import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;import org.mybatis.generator.internal.DefaultCommentGenerator;import org.mybatis.generator.internal.util.StringUtility;import java.util.Properties;public class CommentGenerator extends DefaultCommentGenerator { private boolean addRemarkComments = false ; private static final String EXAMPLE_SUFFIX = "Example" ; private static final String MAPPER_SUFFIX = "Mapper" ; private static final String API_MODEL_PROPERTY_FULL_CLASS_NAME = "io.swagger.annotations.ApiModelProperty" ; @Override public void addConfigurationProperties (Properties properties) { super .addConfigurationProperties(properties); this .addRemarkComments = StringUtility.isTrue(properties.getProperty("addRemarkComments" )); } @Override public void addFieldComment (Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) { String remarks = introspectedColumn.getRemarks(); if (addRemarkComments && StringUtility.stringHasValue(remarks)) { if (remarks.contains("\"" )) { remarks = remarks.replace("\"" , "'" ); } field.addJavaDocLine("@ApiModelProperty(value = \"" + remarks + "\")" ); } } @Override public void addJavaFileComment (CompilationUnit compilationUnit) { super .addJavaFileComment(compilationUnit); String fullyQualifiedName = compilationUnit.getType().getFullyQualifiedName(); if (!fullyQualifiedName.contains(MAPPER_SUFFIX) && !fullyQualifiedName.contains(EXAMPLE_SUFFIX)) { compilationUnit.addImportedType(new FullyQualifiedJavaType (API_MODEL_PROPERTY_FULL_CLASS_NAME)); } } }
最后编写一个Generator
类用于生成代码,直接运行main
方法即可生成所有代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package com.t1k.mall.mbg;import org.mybatis.generator.api.MyBatisGenerator;import org.mybatis.generator.config.Configuration;import org.mybatis.generator.config.xml.ConfigurationParser;import org.mybatis.generator.internal.DefaultShellCallback;import java.io.InputStream;import java.util.ArrayList;import java.util.List;public class Generator { public static void main (String[] args) throws Exception { List<String> warnings = new ArrayList <>(); boolean overwrite = true ; InputStream is = Generator.class.getResourceAsStream("/generatorConfig.xml" ); ConfigurationParser cp = new ConfigurationParser (warnings); Configuration config = cp.parseConfiguration(is); is.close(); DefaultShellCallback callback = new DefaultShellCallback (overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator (config, callback, warnings); myBatisGenerator.generate(null ); for (String warning : warnings) { System.out.println(warning); } } }
一切准备就绪,执行main
方法,生成代码结构信息如下
基本CRUD操作
查看MBG生成的Mapper
接口,发现已经包含了基本的CRUD方法,具体SQL实现也已经在mapper.xml
中生成了,单表CRUD直接调用对应方法即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public interface UmsAdminMapper { long countByExample (UmsAdminExample example) ; int deleteByExample (UmsAdminExample example) ; int deleteByPrimaryKey (Long id) ; int insert (UmsAdmin record) ; int insertSelective (UmsAdmin record) ; List<UmsAdmin> selectByExample (UmsAdminExample example) ; UmsAdmin selectByPrimaryKey (Long id) ; int updateByExampleSelective (@Param("record") UmsAdmin record, @Param("example") UmsAdminExample example) ; int updateByExample (@Param("record") UmsAdmin record, @Param("example") UmsAdminExample example) ; int updateByPrimaryKeySelective (UmsAdmin record) ; int updateByPrimaryKey (UmsAdmin record) ; }public interface UmsAdminMapper { long countByExample (UmsAdminExample example) ; int deleteByExample (UmsAdminExample example) ; int deleteByPrimaryKey (Long id) ; int insert (UmsAdmin record) ; int insertSelective (UmsAdmin record) ; List<UmsAdmin> selectByExample (UmsAdminExample example) ; UmsAdmin selectByPrimaryKey (Long id) ; int updateByExampleSelective (@Param("record") UmsAdmin record, @Param("example") UmsAdminExample example) ; int updateByExample (@Param("record") UmsAdmin record, @Param("example") UmsAdminExample example) ; int updateByPrimaryKeySelective (UmsAdmin record) ; int updateByPrimaryKey (UmsAdmin record) ; }
生成代码中有一些Example类,如UmsAdminExample
,可以把它理解为一个条件构造器,用于构建SQL语句中的各种条件
利用好MBG生成的代码即可完成单表的CRUD操作,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 @Service public class UmsAdminServiceImpl implements UmsAdminService { @Resource private UmsAdminMapper mbgUmsAdminMapper; @Resource private MyUmsAdminMapper myUmsAdminMapper; @Override public void create (UmsAdmin entity) { mbgUmsAdminMapper.insert(entity); } @Override public void update (UmsAdmin entity) { mbgUmsAdminMapper.updateByPrimaryKeySelective(entity); } @Override public void delete (Long id) { mbgUmsAdminMapper.deleteByPrimaryKey(id); } @Override public UmsAdmin select (Long id) { return mbgUmsAdminMapper.selectByPrimaryKey(id); } @Override public List<UmsAdmin> listAll (Integer pageNum, Integer pageSize) { PageHelper.startPage(pageNum, pageSize); return mbgUmsAdminMapper.selectByExample(new UmsAdminExample ()); } }
进阶使用 条件查询
使用Example类构建查询条件可以很方便地实现条件查询
这里以用户名和状态查询后台用户并按创建时间降序排序为例,SQL实现如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 SELECT id, username, PASSWORD, icon, email, nick_name, note, create_time, login_time, STATUS FROM ums_admin WHERE ( username = 'macro' AND STATUS IN ( 0, 1 ) ) ORDER BY create_time DESC;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override public List<UmsAdmin> list (Integer pageNum, Integer pageSize, String username, List<Integer> statusList) { PageHelper.startPage(pageNum, pageSize); UmsAdminExample umsAdminExample = new UmsAdminExample (); UmsAdminExample.Criteria criteria = umsAdminExample.createCriteria(); if (StrUtil.isNotEmpty(username)){ criteria.andUsernameEqualTo(username); } criteria.andStatusIn(statusList); umsAdminExample.setOrderByClause("create_time desc" ); return mbgUmsAdminMapper.selectByExample(umsAdminExample); }
子查询
使用MBG生成的代码并不能实现子查询,需要自己手写SQL实现
这里以按角色id查询后台用户为例,首先定义一个MyUmsAdminMapper
接口,这里约定com.**.dao
包下存放的都是自定义SQL实现的Mapper
文件,首先在MyUmsAdminMapper
接口中添加subList
方法
1 2 3 4 public interface MyUmsAdminMapper { List<UmsAdmin> subList (@Param("roleId") Long roleId) ; }
然后创建一个MyUmsAdminMapper.xml
文件,对应MyUmsAdminMapper
接口的SQL实现,注意使用的BaseResultMap
MBG已经帮我们生成好了,无需自己手写
1 2 3 4 <select id ="subList" resultMap ="com.t1k.mall.mbg.mapper.UmsAdminMapper.BaseResultMap" > select * from ums_admin where id in (select admin_id from ums_admin_role_relation where role_id = #{roleId}) </select >
Group和Join查询
Group和Join查询也不能使用MBG生成的代码实现
这里以按角色统计后台用户数量为例,首先在Mapper
接口中添加groupList
方法
1 2 3 4 public interface MyUmsAdminMapper { List<RoleStatDto> groupList () ; }
然后在mapper.xml
中添加对应的SQL实现,可以通过给查询出来的列起别名,直接把列映射到resultType
所定义的对象中去
1 2 3 4 5 6 7 8 9 10 11 12 <select id ="groupList" resultType ="com.t1k.mall.domain.RoleStatDto" > select ur.id as roleId, ur.name as roleName, count(ua.id) as count from ums_role ur left join ums_admin_role_relation uarr on ur.id = uarr.role_id left join ums_admin ua on uarr.admin_id = ua.id group by ur.id </select >
条件删除
条件删除直接使用Example类构造删除条件即可
1 delete from ums_admin where username = 'test'
1 2 3 4 5 6 7 8 9 @Override public void deleteByUsername (String username) { UmsAdminExample umsAdminExample = new UmsAdminExample (); if (StrUtil.isNotEmpty(username)){ umsAdminExample.createCriteria().andUsernameEqualTo(username); } mbgUmsAdminMapper.deleteByExample(umsAdminExample); }
条件修改
条件修改和条件删除类似,直接使用Example类构造修改条件,然后传入修改参数即可
这里以按指定id修改后台用户的状态为例,SQL实现如下
1 update ums_admin set status = 1 where id in (1, 2)
1 2 3 4 5 6 7 8 9 10 11 @Override public void updateByIds (List<Long> ids, Integer status) { UmsAdminExample umsAdminExample = new UmsAdminExample (); UmsAdminExample.Criteria criteria = umsAdminExample.createCriteria(); criteria.andIdIn(ids); UmsAdmin umsAdmin = new UmsAdmin (){{ setStatus(status); }}; mbgUmsAdminMapper.updateByExample(umsAdmin, umsAdminExample); }
一对多查询
一对多查询无法直接使用MBG生成的代码实现,需要手写SQL实现,并使用resultMap
来进行结果集映射
这里以按id查询后台用户信息(包含对应角色列表)为例,先在mapper
接口中添加selectWithRoleList
方法
1 2 3 4 public interface MyUmsAdminMapper { AdminRoleDto selectWithRoleList (@Param("id") Long id) ; }
然后在mapper.xml
中添加对应的SQL实现,这里有个小技巧,可以给角色表查询出来的列取个别名,如添加一个role_
前缀
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <select id ="selectWithRoleList" resultMap ="AdminWithRoleResult" > select ua.*, ur.name as role_name, ur.description as role_description, ur.admin_count as role_adminCount, ur.create_time as role_createTime, ur.sort as role_sort, ur.status as role_status from ums_admin ua left join ums_admin_role_relation uarr on ua.id = uarr.admin_id left join ums_role ur on uarr.role_id = ur.id where ua.id = #{id} </select >
然后定义一个叫AdminRoleResult
的resultMap
,通过collection
标签直接将以role_
开头的列映射到UmsRole
对象中去即可
1 2 3 4 5 6 <resultMap id ="AdminWithRoleResult" type ="com.t1k.mall.domain.AdminRoleDto" extends ="com.t1k.mall.mbg.mapper.UmsAdminMapper.BaseResultMap" > <collection property ="roleList" resultMap ="com.t1k.mall.mbg.mapper.UmsRoleMapper.BaseResultMap" columnPrefix ="role_" > </collection > </resultMap >
一对一查询
一对一查询无法直接使用MBG生成的代码实现,需要手写SQL实现,并使用resultMap
来进行结果集映射
这里以按id查询资源信息(包括分类信息)为例,现在mapper
接口中添加selectResourceWithCate
方法
1 2 3 4 public interface MyUmsAdminMapper { ResourceWithCateDto selectResourceWithCate (@Param("id") Long id) ; }
然后在mapper.xml
中添加对应SQL实现,可以给分类表查询出来的列取个别名,如添加一个cate_
前缀
1 2 3 4 5 6 7 8 9 10 11 12 13 <select id ="selectResourceWithCate" resultMap ="ResourceWithCateResult" > select ur.*, urc.id as cate_id, urc.create_time as cate_createTime, urc.name as cate_name, urc.sort as cate_sort from ums_resource ur left join ums_resource_category urc on ur.category_id = urc.id where ur.id = #{id} </select >
然后定义一个叫做ResourceWithCateResult
的resultMap
,通过association
标签直接将以cate_
开头的列映射到UmsResourceCategory
对象中去即可
1 2 3 4 5 6 7 <resultMap id ="ResourceWithCateResult" type ="com.t1k.mall.domain.ResourceWithCateDto" extends ="com.t1k.mall.mbg.mapper.UmsResourceMapper.BaseResultMap" > <association property ="resourceCategory" resultMap ="com.t1k.mall.mbg.mapper.UmsResourceCategoryMapper.BaseResultMap" columnPrefix ="cate_" > </association > </resultMap >