目录
写在前面
一、环境准备:
1.1、导入依赖
1.2、yaml配置和mybatis的配置文件一致
1.3、IUser实体类
1.4、UserMapper
二、使用
测试须知
2.1、基础增删改查
2.2、批量操作
2.3、查询条件构造器【QueryWrapper】使用
2.4、修改条件构【UpdateWrapper】造器使用
三、减少硬编码
四、代码生成器
mybatis-plus顾名思义就是mybatis的增强工具。对于mybatis的功能只做扩展、不做改变。体现在内置的Mapper对CRUD进行了封装、只需要通过简单的配置即可实现增删改查操作。而不用编写XML和SQL。
前置的项目搭建和数据库表:
传送门:
使用IDEA新建一个springboot项目
springboot整合mybatis
将springboot 整合mybatis的依赖替换为整合mybatis-plus的起步依赖;
com.baomidou
mybatis-plus-boot-starter
3.4.0
IDEA按照一个插件Maven Helper可以查看是否有依赖冲突。
端口、数据库、mybatis-plus日志输出、驼峰映射、xml位置等
server: port: 8889 spring: datasource: url: jdbc:mysql://localhost:3308/boot_mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&AllowPublicKeyRetrieval=True username: root password: root mybatis-plus: mapper-locations: mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true type-aliases-package: com.example.demo.entity
绑定表名、主键名
@Data
@TableName("t_user")
public class IUser {
/**
* 指定主键名、主键生产策略
*/
@TableId(value = "u_id", type = IdType.AUTO)
private Integer uId;
/**
*指定列名,若一致可以不用指定
*/
@TableField("user_name")
private String userName;
private String email;
private String passWord;
private Date birth;
private int gender;
}
只要继承BaseMapper<~>即可、其他方法和xml可以删掉。
@Mapper
public interface IUserMapper extends BaseMapper {}
IUserMapper继承BaseMapper<~>后就可以不用编写XML来实现了
本文直接在测试类中注入IUserMapper、编写测试方法进行测试。service层、controller层就不写了
@Autowired private IUserMapper userMapper;
可以看到,自己并没有新建方法,而userMapper可以调用BaseMapper提供的众多方法。
可以看到BaseMapper提供的方法需要的参数有字符串、实体类、map、条件构造器等。下文将使用一些用例来测试这些方法。为了增加观感、只展示如何使用、执行结果、SQL日志就不截图占用篇幅了。
2.1.1 新增一条User数据
@Test public void insert(){ IUser user = new IUser(); user.setUserName("韩信"); user.setPassWord("123"); user.setEmail("[email protected]"); userMapper.insert(user); }
2.1.2 根据条件删除User
根据ID删除
@Test public void deleteById(){ userMapper.deleteById(84); }
根据某列精准匹配删除
@Test public void deleteByMap(){ Map
map = new HashMap<>(); map.put("user_name","韩信"); userMapper.deleteByMap(map); }
2.1.3 修改数据User信息
根据ID修改
@Test public void updateById(){ IUser user = new IUser(); user.setUserName("李白"); user.setUId(81); userMapper.updateById(user); }
2.1.3 根据条件查询用户
查询全部用户
@Test public void selectList(){ userMapper.selectList(null); }
根据ID查询
@Test public void selectById(){ userMapper.selectById(81); }
根据某列精确匹配
@Test public void selectByMap(){ Map
map = new HashMap<>(); map.put("user_name","李白"); userMapper.selectByMap(map); }
2.2.1 批量新增
@Test public void batchUpdate(){ IUser user1 = new IUser(); IUser user2 = new IUser(); IUser user3 = new IUser(); user1.setUserName("彭于晏"); user2.setUserName("吴彦祖"); user3.setUserName("胡歌"); user1.setPassWord("123"); user2.setPassWord("123"); user3.setPassWord("123"); ArrayList
userList = new ArrayList<>(); userList.add(user1); userList.add(user2); userList.add(user3); userList.forEach(user -> { userMapper.insert(user); }); }
2.2.2 批量删除
@Test public void deleteBatchIds(){ List
ids = new ArrayList<>(); ids.add(85); ids.add(86); ids.add(87); ids.add(89); userMapper.deleteBatchIds(ids); }
2.2.3 批量查询
根据ids
@Test public void selectBatchIds(){ List
ids = new ArrayList<>(); ids.add(85); ids.add(86); ids.add(87); ids.add(89); userMapper.selectBatchIds(ids); }
条件构造器就是通过链式编程的形式构造where后面的SQL
比如:查询user_name="李白" and email like "123" 的用户
@Test public void selectListByQueryWrapper(){ QueryWrapper
queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_name","李白") .like("email","123"); userMapper.selectList(queryWrapper); } 比如:查询user_name="李白" and pass_word like "123" 的用户
@Test public void selectMapsByQueryWrapper(){ QueryWrapper
queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_name","李白") .like("pass_word","123"); userMapper.selectMaps(queryWrapper); } 但是存在许多硬编码。
也是通过链式编程的方式拼接修改条件;
比如,将用户名为张三的密码修改为[email protected]
@Test public void updateByUpdateWrapper(){ UpdateWrapper
updateWrapper = new UpdateWrapper<>(); IUser user = new IUser(); updateWrapper.eq("user_name","张三") .set("email","[email protected]"); userMapper.update(user,updateWrapper); } ,
也是存在字段的硬编码
以上可否已经感觉到了mybatis-plus的强大之处?可还记得实体类做了数据库字段和实体属性的映射。那用使用条件构造器和修改构造器的时候还要再确认数据库字段是否显得字段映射有点多余?
开个玩笑,修改一个构造器就可以减少硬编码了。
【LambdaQueryWrapper】来减少硬编码、直接通过类获取属性的方式得到字段
比如查询姓"张"的所有用户
@Test public void updateByLambdaQueryWrapper(){ LambdaQueryWrapper
lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.like(IUser::getUserName,"张"); userMapper.selectList(lambdaQueryWrapper); }
【LambdaUpdateWrapper】减少硬编码
将张三的邮箱修改为[email protected]
@Test public void updateByLambdaUpdateWrapper(){ LambdaUpdateWrapper
lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); IUser user = new IUser(); lambdaUpdateWrapper.eq(IUser::getUserName,"张三") .set(IUser::getEmail,"[email protected]"); userMapper.update(user,lambdaUpdateWrapper); }
上述就是springboot整合mybatis-plus的大部分内容了。
任何重复、有结构的数据都可以用代码生成。这里的代码生成器是指通过表名一键生成项目的目录结构、实体类、xxx.xml等。
准备一个springboot空项目:
准备一张数据库表:
CREATE TABLE `t_user` ( `u_id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `user_name` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '用户登录名', `email` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '邮箱', `pass_word` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT '密码', `birth` date DEFAULT NULL COMMENT '生日', `start_date` date DEFAULT NULL COMMENT '注册时间', `update_date` date DEFAULT NULL COMMENT '最后修改时间', `gender` bigint NOT NULL DEFAULT '2' COMMENT '性别,0:男,1:女,2:保密', `is_action` int DEFAULT NULL COMMENT '逻辑删除字段', `version` int DEFAULT NULL COMMENT '乐观锁配置', PRIMARY KEY (`u_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=88 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;
引入依赖:mybatis-plus的版本不一样配置也有所不同
mysql mysql-connector-java com.baomidou mybatis-plus-boot-starter 3.4.0 org.apache.velocity velocity-engine-core 2.0 com.baomidou mybatis-plus-generator 3.4.0
yml
spring: datasource: url: jdbc:mysql://localhost:3308/generate?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&AllowPublicKeyRetrieval=True username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver
测试工具类
/** * @author Alex */ public class GeneratorUtils { public static void main(String[] args) { autoGenerator(); } public static void autoGenerator() { AutoGenerator autoGenerator = new AutoGenerator(); autoGenerator.setDataSource(getDataSourceConfig()); autoGenerator.setGlobalConfig(getGlobalConfig()); autoGenerator.setPackageInfo(getPackageInfo()); autoGenerator.setStrategy(getStrategyConfig()); autoGenerator.execute(); } /** * 设置数据源 * @return */ public static DataSourceConfig getDataSourceConfig(){ DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3308/generate?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&AllowPublicKeyRetrieval=True"); dsc.setSchemaName("public"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("root"); dsc.setDbType(DbType.MYSQL); return dsc; } /** * 设置全局配置 * @return */ public static GlobalConfig getGlobalConfig(){ GlobalConfig gc = new GlobalConfig(); String path = System.getProperty("user.dir"); gc.setOutputDir(path+"/src/main/java");//参数是一个目录,所以需要获取当前系统目录 gc.setAuthor("Alex"); gc.setOpen(true);//是否打开资源管理器 gc.setFileOverride(true);//是否覆盖已经生成的 gc.setServiceName("%sService");//去service的I前缀 gc.setIdType(IdType.INPUT);// id生成策略 gc.setDateType(DateType.ONLY_DATE); return gc; } /** *包配置 * @return */ public static PackageConfig getPackageInfo(){ PackageConfig pc = new PackageConfig(); pc.setModuleName("common"); pc.setParent("com.example.demo"); pc.setEntity("entity"); pc.setMapper("mapper"); pc.setService("service"); pc.setController("controller"); return pc; } /** * 策略配置 * @return */ public static StrategyConfig getStrategyConfig(){ StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel);// 下划线转驼峰命名 strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 设置映射的表名,多张表 strategy.setInclude("t_user"); strategy.setEntityLombokModel(true);// 是否启用lombok开启注解 strategy.setLogicDeleteFieldName("isAction");//设置逻辑删除字段 // 时间自动填充配置 TableFill startDate = new TableFill("startDate", FieldFill.INSERT); TableFill updateDate = new TableFill("updateDate", FieldFill.UPDATE); ArrayList
list = new ArrayList<>(); list.add(startDate); list.add(updateDate); strategy.setTableFillList(list); // 乐观锁配置 strategy.setVersionFieldName("version"); // rustful 格式 strategy.setRestControllerStyle(true); return strategy; } }
生成目录:生成common模块的项目项目结构
调整:
- 移动下xxxMapper.xml的位置,并在xxxxMapper的接口上加上@Mapper注解
- 启动类上添加:@MapperScan("com.example.demo.mapper")
测试使用:
新增一个用户:
@Autowired private TUserMapper userMapper; @Test public void insert(){ TUser user = new TUser(); user.setUserName("王维"); user.setPassWord("qwe@qwe"); userMapper.insert(user); }
结果:
补充:由于配置的参数都可以是固定的、需要手动改变的只有数据库的表名。因此将将其打包成工具、连接数据库后指定下表名。即可生成结构相同的目录结构、具体需要什么是什么目录根据实际情况而定。