目录
1 、Mybatis-Plus简介
2 、快速入门
2.1、 创建数据库及表
2.2 工程搭建
2.2.1 创建springBoot工程
2.2.2 导入依赖
2.2.3 配置application.yml
2.2.4 启动类
2.2.4 编写pojo
2.2.5 编写mapper接口和配置文件
2.2.6 编写测试用例,加入junit的依赖,测试类不能使用Test类名,测试类的包目录和启动类的路径一致
3 通用CRUD
3.1插入 *** 作
3.1.1、方法定义:
3.1.2、测试用例:
3.1.4、@TableField
3.2、更新 *** 作
3.2.1、根据id更新
3.2.2、根据条件更新
3.3、删除 *** 作
3.3.1、deleteById
3.3.2、deleteByMap
3.3.3、delete
3.3.4、deleteBatchIds
3.4、查询 *** 作
3.4.1、selectById单个查询
3.4.2、selectBatchIds 批量查询
3.4.3、selectOne 根据条件查询一条数据
3.4.4、selectCount 根据条件,查询总条数
3.4.5、selectList 根据条件查询全部记录
3.4.6、selectPage 根据条件查询全部并分页
3.5、SQL注入的原理
4、配置
4.1、基本配置
4.1.1、confifigLocation
4.1.2、mapperLocations
4.1.3、typeAliasesPackage
4.2、进阶配置
4.2.1、mapUnderscoreToCamelCase 是否自动开启驼峰命名映射
4.3、DB 相关策略配置
4.3.1、idType
4.3.2、tablePrefifix
5、条件构造器
5.1、allEq
5.2、基本比较 *** 作
5.3、模糊查询
5.4、排序
5.5、逻辑查询
5.6、select
5.7、lambda
6、Mybatisplus的service的封装
6.1、com.baomidou.mybatisplus.extension.service.IService接口
6. 2、com.baomidou.mybatisplus.extension.service.impl.ServiceImpl类
6.3、测试用例
6.3.1、 自定义业务层接口,继承IService
6.3.2、自定义业务层实现类,继承ServiceImpl:
6.3.3、测试类:
7、代码生成器
7.1、 代码生成说明
7.2、 代码生成
7.2.1、导入依赖
7.2.2、代码生成是基于模板做的,这里采用的freemark模块来生成,把template文件夹放到resources
7.2.3、编写生产代码的类CodeGenerator
7.2.4、生成代码
8、MybatisX 快速开发插件
1 、Mybatis-Plus简介
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。该框架由baomidou(苞米豆)组织开发并且开源的。官网:mybatis.plus 或 https://mp.baomidou.com/,码云地址:baomidou: 苞米豆,为提高生产率而生!
2 、快速入门 2.1、 创建数据库及表
-- 创建测试表 CREATE TABLE `tb_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_name` varchar(20) NOT NULL COMMENT '用户名', `password` varchar(20) NOT NULL COMMENT '密码', `name` varchar(30) DEFAULT NULL COMMENT '姓名', `age` int(11) DEFAULT NULL COMMENT '年龄', `email` varchar(50) DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -- 插入测试数据 INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('1', 'zhangsan', '123456', '张三', '18', '[email protected]'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('2', 'lisi', '123456', '李四', '20', '[email protected]'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('3', 'wangwu', '123456', '王五', '28', '[email protected]'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('4', 'zhaoliu', '123456', '赵六', '21', '[email protected]'); INSERT INTO `tb_user` (`id`, `user_name`, `password`, `name`, `age`, `email`) VALUES ('5', 'sunqi', '123456', '孙七', '24', '[email protected]');2.2 工程搭建 2.2.1 创建springBoot工程 2.2.2 导入依赖
org.springframework.boot spring-boot-starter-parent2.1.5.RELEASE org.springframework.boot spring-boot-starterorg.springframework.boot spring-boot-starter-loggingorg.springframework.boot spring-boot-starter-testtest org.projectlombok lomboktrue com.baomidou mybatis-plus-boot-starter3.1.1 mysql mysql-connector-java5.1.47 org.slf4j slf4j-log4j12com.baomidou mybatis-plus-generator3.1.2 org.springframework.boot spring-boot-maven-plugin
log4j.properties:
log4j.rootLogger=DEBUG,A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n2.2.3 配置application.yml
spring: application: name: mybatisplusspringboot datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username: root password: 123 # 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置 mybatis-plus: mapper-locations: classpath*:mybatis @SpringBootApplication @MapperScan(basePackages = "com.chen.mp.mapper")//用于扫描mapper接口文件 public class MpApplication { public static void main(String[] args) { System.out.println("ss"); SpringApplication.run(MpApplication.class,args); } }2.2.4 编写pojo
package com.chen.mp.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @Data//使用lombok完成get和set @TableName("tb_user")//对应数据库的表名 public class User { @TableId(value = "ID",type = IdType.AUTO) private Long id; @TableField("USER_NAME")//此属性名称和数据库中字段名称不符合,所以显示的映射 private String userName;//此属性名称和数据库中字段名称相同,所以隐式的映射 private String password; private String name; private Integer age; private String email; }2.2.5 编写mapper接口和配置文件
package com.chen.mp.mapper; import com.baomidou.mybatisplus.core.mapper.baseMapper; import com.chen.mp.pojo.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper extends baseMapper{ }
在resources目录下新建一个文件夹mybatis,专门存放mapper配置文件,用于扩展自定义的sql
2.2.6 编写测试用例,加入junit的依赖,测试类不能使用Test类名,测试类的包目录和启动类的路径一致
package com.chen; import com.chen.mp.mapper.UserMapper; import com.chen.mp.pojo.User; 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.SpringRunner; import java.util.List; @RunWith(SpringRunner.class)//使用springrunner运行器 @SpringBootTest(classes = MpApplication.class)//启用springboot测试,加载Springboot配置文件 public class UserMapperTest { @Autowired private UserMapper userMapper; //查询所有 @Test public void testSelectAll(){ List3 通用CRUDuserList = userMapper.selectList(null); System.out.println(userList); } //查询一个 @Test public void testSelectOne(){ User user = userMapper.selectById(1); System.out.println(user); } //保存 @Test public void testSave(){ User user = new User(); user.setUserName("xiaozhao"); user.setAge(40); user.setPassword("xiaozhao"); user.setName("小赵"); user.setEmail("[email protected]"); userMapper.insert(user); } //修改 @Test public void testUpdate(){ User user = new User(); user.setId(1228242594492923909l); user.setName("老赵"); userMapper.updateById(user); } //删除 @Test public void testDelete(){ int i = userMapper.deleteById(1228242594492923909l); } }
完成了demo的搭建,接下来查看我们继承的baseMapper中的单表 *** 作
3.1插入 *** 作 3.1.1、方法定义: 3.1.2、测试用例:@Autowired private UserMapper userMapper; @Test public void testInsert(){ User user = new User(); user.setAge(20); user.setEmail("[email protected]"); user.setName("曹 *** "); user.setUserName("caocao"); user.setPassword("123456"); //返回的result是受影响的行数,并不是自增后的id int result = this.userMapper.insert(user); System.out.println("result = " + result); System.out.println(user.getId()); //自增后的id会回填到对象中
如何设置id的生成策略 ,MP支持的id策略(查看IdType类):
package com.baomidou.mybatisplus.annotation; public enum IdType { AUTO(0), NONE(1), INPUT(2), ID_WORKER(3), UUID(4), ID_WORKER_STR(5); private final int key; private IdType(int key) { this.key = key; } public int getKey() { return this.key; } }3.1.4、@TableField
在MP中通过@TableField注解可以指定字段的一些属性,常常解决的问题有2个:
- 对象中的属性名和字段名不一致的问题(非驼峰)
- 对象中的属性字段在表中不存在的问题
在MP中,更新 *** 作有2种,一种是根据id更新,另一种是根据条件更新。
3.2.1、根据id更新方法定义:
测试:
@Autowired private UserMapper userMapper; @Test public void testUpdateById() { User user = new User(); user.setId(6L); //主键 user.setAge(21); //更新的字段 //根据id更新,更新不为null的字段 userMapper.updateById(user); }3.2.2、根据条件更新
方法定义:
测试:
第一种:通过QueryMapper对象
@Autowired private UserMapper userMapper; @Test public void testUpdate() { User user = new User(); user.setAge(22); //更新的字段 QueryWrapperwrapper = new QueryWrapper<>(); //更新的条件 wrapper.eq("id", 6); //执行更新 *** 作 int result = this.userMapper.update(user, wrapper); System.out.println("result = " + result);
第二种: UpdateWrapper对象
@Test public void testUpdate() { //更新的条件以及字段 UpdateWrapper3.3、删除 *** 作 3.3.1、deleteByIdwrapper = new UpdateWrapper<>(); wrapper.eq("id", 6).set("age", 23); //执行更新 *** 作 int result = this.userMapper.update(null, wrapper); System.out.println("result = " + result); }
方法定义:
测试用例:
@Autowired private UserMapper userMapper; @Test public void testDeleteById() { //执行删除 *** 作 int result = this.userMapper.deleteById(6L); System.out.println("result = " + result); }3.3.2、deleteByMap
方法定义:
测试:
@Autowired private UserMapper userMapper; @Test public void testDeleteByMap() { Map3.3.3、deletecolumnMap = new HashMap<>(); columnMap.put("age",20); columnMap.put("name","张三"); //将columnMap中的元素设置为删除的条件,多个之间为and关系 //执行的sql语句:DELETE FROM tb_user WHERe name = ? AND age = ? int result = this.userMapper.deleteByMap(columnMap); System.out.println("result = " + result); }
方法定义:
测试:
@Test public void testDeleteByMap() { User user = new User(); user.setAge(20); user.setName("张三"); //将实体对象进行包装,包装为 *** 作条件 QueryWrapper3.3.4、deleteBatchIdswrapper = new QueryWrapper<>(user); int result = this.userMapper.delete(wrapper); System.out.println("result = " + result); }
方法定义:
测试:
@Test public void testDeleteByMap() { //根据id集合批量删除 int result = this.userMapper.deleteBatchIds(Arrays.asList(1L,10L,20L)); System.out.println("result = " + result); }3.4、查询 *** 作
MP提供了多种查询 *** 作,包括根据id查询、批量查询、查询单条数据、查询列表、分页查询等 *** 作。
3.4.1、selectById单个查询方法定义:
测试:
@Autowired private UserMapper userMapper; @Test public void testSelectById() { //根据id查询数据 User user = this.userMapper.selectById(2L); System.out.println("result = " + user); }3.4.2、selectBatchIds 批量查询
方法定义:
测试:
@Autowired private UserMapper userMapper; @Test public void testSelectBatchIds() { //根据id集合批量查询 List3.4.3、selectOne 根据条件查询一条数据users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L)); for (User user : users) { System.out.println(user); } }
方法定义:
测试:
@Test public void testSelectOne() { QueryWrapper3.4.4、selectCount 根据条件,查询总条数wrapper = new QueryWrapper (); wrapper.eq("name", "李四"); //根据条件查询一条数据,如果结果超过一条会报错 User user = this.userMapper.selectOne(wrapper); System.out.println(user); }
方法定义:
测试:
@Test public void testSelectCount() { QueryWrapper3.4.5、selectList 根据条件查询全部记录wrapper = new QueryWrapper (); //年龄大于23岁 wrapper.gt("age", 23); //根据条件查询数据条数 Integer count = this.userMapper.selectCount(wrapper); System.out.println("count = " + count); }
方法定义:
测试:
@Test public void testSelectList() { QueryWrapper3.4.6、selectPage 根据条件查询全部并分页 配置分页插件(自定义一个类):wrapper = new QueryWrapper (); //年龄大于23岁 wrapper.gt("age", 23); //根据条件查询数据 List users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println("user = " + user); } }
package com.chen.mp.config; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.context.annotation.Bean; @Configurable @MapperScan("com.chen.mp.mapper") //设置mapper接口的扫描包 public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }
方法定义:
测试:
@Test public void testSelectPage() { QueryWrapper3.5、SQL注入的原理 在 MP 中, ISqlInjector 负责 SQL 的注入工作,它是一个接口, AbstractSqlInjector 是它的实现类,实现关系如下:wrapper = new QueryWrapper (); //年龄大于20岁 wrapper.gt("age", 20); //参数:当前页,每页条数 Page page = new Page<>(1,1); //根据条件查询数据 IPage iPage = this.userMapper.selectPage(page, wrapper); System.out.println("数据总条数:" + iPage.getTotal()); System.out.println("总页数:" + iPage.getPages()); List users = iPage.getRecords(); for (User user : users) { System.out.println("user = " + user); } }
在AbstractSqlInjector中,主要是由inspectInject()方法进行注入的,如下:
@Override public void inspectInject( MapperBuilderAssistant builderAssistant, Class> mapperClass) { Class> modelClass = extractModelClass(mapperClass); if (modelClass != null) { String className = mapperClass.toString(); Set在实现方法中, methodList.forEach(m - > m.inject(builderAssistant, mapperClass, modelClass, tableInfo)) ; 是关键,循环遍历方法,进行注入。 最终调用抽象方法 injectMappedStatement 进行真正的注入:mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration()); if (!mapperRegistryCache.contains(className)) { List methodList = this.getMethodList(); if (CollectionUtils.isNotEmpty(methodList)) { TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass); // 循环注入自定义方法 methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo)); } else { logger.debug(mapperClass.toString() + ", No effective injection method was found."); } mapperRegistryCache.add(className); } } }
public abstract MappedStatement injectMappedStatement(Class> mapperClass, Class > modelClass, TableInfo tableInfo);查看该方法的实现:
以SelectById为例查看:
public class SelectById extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) { SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID; SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, false), tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, false)), Object.class); return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, tableInfo); } }可以看到,生成了 SqlSource 对象,再将 SQL 通过 addSelectMappedStatement方法添加到 MappedStatement 中。 4、配置 在 MP 中有大量的配置,其中有一部分是 Mybatis 原生的配置,另一部分是 MP 的配置,详情: https://mybatis.plus/c onfifig/ 下面我们对常用的配置做讲解 4.1、基本配置 4.1.1、confifigLocation MyBatis 配置文件位置,如果您有单独的 MyBatis 配置,请将其路径配置到 confifigLocation 中。 MyBatis Confifiguration 的具体内容请参考 MyBatis 官方文档 Spring Boot :
mybatis-plus.config-location = classpath:mybatis-config.xml
Spring MVC:
4.1.2、mapperLocations
MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法( XML 中有自定义实现),需要进行 该配置,告诉 Mapper 所对应的 XML 文件位置。 Spring Boot :Maven 多模块项目的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML 文件)
mybatis-plus.mapper-locations = classpath*:mybatis public class CodeGenerator { // TODO 修改服务名以及数据表名 private static final String SERVICE_NAME = "mp"; private static final String DATA_SOURCE_USER_NAME = "root"; private static final String DATA_SOURCE_PASSWORD = "123"; private static final String[] TABLE_NAMES = new String[]{ "tb_user" }; // TODO 默认生成entity,需要生成DTO修改此变量 // 一般情况下要先生成 DTO类 然后修改此参数再生成 PO 类。 private static final Boolean IS_DTO = false; public static void main(String[] args) { // 代码生成器 AutoGenerator mpg = new AutoGenerator(); // 选择 freemarker 引擎,默认 Velocity mpg.setTemplateEngine(new FreemarkerTemplateEngine()); // 全局配置 GlobalConfig gc = new GlobalConfig(); gc.setFileOverride(true); gc.setOutputDir(System.getProperty("user.dir") + "/src/main/java"); gc.setAuthor("chenfan"); gc.setOpen(false); gc.setSwagger2(false); gc.setServiceName("%sService"); gc.setbaseResultMap(true); gc.setbaseColumnList(true); if (IS_DTO) { gc.setSwagger2(true); gc.setEntityName("%sDTO"); } mpg.setGlobalConfig(gc); // 数据库配置 DataSourceConfig dsc = new DataSourceConfig(); dsc.setDbType(DbType.MYSQL); dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&useSSL=false&characterEncoding=utf8"); dsc.setDriverName("com.mysql.jdbc.Driver"); dsc.setUsername(DATA_SOURCE_USER_NAME); dsc.setPassword(DATA_SOURCE_PASSWORD); mpg.setDataSource(dsc); // 包配置 PackageConfig pc = new PackageConfig(); pc.setModuleName(SERVICE_NAME); pc.setParent("com.chen"); pc.setServiceImpl("service.impl"); pc.setXml("mapper"); mpg.setPackageInfo(pc); // 自定义配置 InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; ListfocList = new ArrayList<>(); focList.add(new FileOutConfig("/templates/mapper.xml.ftl") { @Override public String outputFile(TableInfo tableInfo) { // 自定义输入文件名称 return System.getProperty("user.dir") + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); cfg.setFileOutConfigList(focList); mpg.setCfg(cfg); // 设置模板 TemplateConfig tc = new TemplateConfig(); mpg.setTemplate(tc); // 策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); strategy.setRestControllerStyle(true); strategy.setInclude(TABLE_NAMES); strategy.setControllerMappingHyphenStyle(true); strategy.setTablePrefix(pc.getModuleName() + "_"); // Boolean类型字段是否移除is前缀处理 strategy.setEntityBooleanColumnRemoveIsPrefix(true); strategy.setRestControllerStyle(true); mpg.setStrategy(strategy); mpg.execute(); } }
参数说明:
7.2.4、生成代码执行CodeGenerator类中的main方法,就可以生成文件
8、MybatisX 快速开发插件MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins ->输入 mybatisx 搜索并安装。
功能:
-
Java 与 XML 调回跳转
-
Mapper 方法自动生成 XML
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)