1. 快速入门 1. 依赖引入 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <optional > true</optional > </dependency > <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.1.1</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 5.1.47</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-log4j12</artifactId > </dependency >
2. 配置文件 1 2 3 4 5 6 7 8 9 10 11 12 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%n spring.application.name = jyw-mp-springboot spring.datasource.driver-class-name =com.mysql.jdbc.Driver spring.datasource.url =jdbc:mysql://127.0.0.1:3306/mp? useUnicode =true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false spring.datasource.username =root spring.datasource.password =root
3. 编写pojo 1 2 3 4 5 6 7 8 9 10 11 12 @Data @NoArgsConstructor @AllArgsConstructor @TableName("tb_user") public class User { private Long id; private String userName; private String password; private String name; private Integer age; private String email; }
4. 编写mapper 1 2 public interface UserMapper extends BaseMapper <User> {}
5. 编写启动类 1 2 3 4 5 6 7 @MapperScan("cn.jyw.mp.mapper") @SpringBootApplication public class MyApplication { public static void main (String[] args) { SpringApplication.run(MyApplication.class, args); } }
6. 编写测试用例 1 2 3 4 5 6 7 8 9 10 11 12 13 @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest {@Autowired private UserMapper userMapper;@Test public void testSelect () { List<User> userList = userMapper.selectList(null ); for (User user : userList) { System.out.println(user); } } }
2.通用CRUD 2.1 插入操作 1. 方法定义 1 2 3 4 5 6 int insert (T entity) ;
2. 测试用例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testInsert () { User user = new User (); user.setAge(20 ); user.setEmail("123.com" ); user.setName("测试人员" ); user.setUserName("testUser" ); user.setPassword("123456" ); int result = this .userMapper.insert(user); System.out.println("result = " + result); System.out.println(user.getId()); } }
但是这种方法使用了MP生成的id写入了数据库
3. MP支持的id策略: 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 @Getter public enum IdType { AUTO(0 ), NONE(1 ), INPUT(2 ), ID_WORKER(3 ), UUID(4 ), ID_WORKER_STR(5 ); private final int key; IdType(int key) { this .key = key; } }
修改User对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Data @NoArgsConstructor @AllArgsConstructor @TableName("tb_user") public class User { @TableId(type = IdType.AUTO) private Long id; private String userName; private String password; private String name; private Integer age; private String email; }
4. @TableField 在MP中通过@TableField注解可以指定字段的一些属性,常常解决的问题有2个:
对象中的属性名和字段名不一致的问题(非驼峰)
对象中的属性字段在表中不存在的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Data @NoArgsConstructor @AllArgsConstructor @TableName("tb_user") public class User { @TableId(type = IdType.AUTO) private Long id; private String userName; @TableField(select = false) private String password; private String name; private Integer age; @TableField(value = "email") private String mail; @TableField(exist = false) private String address; }
2.2 更新操作 在MP中,更新操作有2种,一种是根据id更新,另一种是根据条件更新。
1. 根据id更新
方法定义:
1 2 3 4 5 6 int updateById (@Param(Constants.ENTITY) T entity) ;
测试
1 2 3 4 5 6 7 8 @Test public void testUpdateById () { User user = new User (); user.setId(6L ); user.setAge(21 ); this .userMapper.updateById(user); }
2. 根据条件更新
方法定义:
1 2 3 4 5 6 7 int update (@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper) ;
测试用例:
1 2 3 4 5 6 7 8 9 10 @Test public void testUpdate () { User user = new User (); user.setAge(22 ); QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("id" , 6 ); int result = this .userMapper.update(user, wrapper); System.out.println("result = " + result);
3.3 删除操作 1. deleteById
方法定义:
1 2 3 4 5 6 int deleteById (Serializable id) ;
测试用例:
1 2 3 4 5 6 @Test public void testDeleteById () { int result = this .userMapper.deleteById(6L ); System.out.println("result = " + result); }
2. deleteByMap
方法定义:
1 2 3 4 5 6 int deleteByMap (@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap) ;
测试用例:
1 2 3 4 5 6 7 8 9 10 @Test public void testDeleteByMap () { Map<String, Object> columnMap = new HashMap <>(); columnMap.put("age" ,20 ); columnMap.put("name" ,"张三" ); int result = this .userMapper.deleteByMap(columnMap); System.out.println("result = " + result); }
3. delete
方法定义:
1 2 3 4 5 6 int delete (@Param(Constants.WRAPPER) Wrapper<T> wrapper) ;
测试用例
1 2 3 4 5 6 7 8 9 10 11 12 @Test public void testDeleteByMap () { User user = new User (); user.setAge(20 ); user.setName("张三" ); QueryWrapper<User> wrapper = new QueryWrapper <>(user); int result = this .userMapper.delete(wrapper); System.out.println("result = " + result); }
4.deleteBatchIds
方法定义:
1 2 3 4 5 6 7 int deleteBatchIds (@Param(Constants.COLLECTION) Collection<? extends Serializable> idList) ;
测试用例:
1 2 3 4 5 6 @Test public void testDeleteByMap () { int result = this .userMapper.deleteBatchIds(Arrays.asList(1L ,10L ,20L )); System.out.println("result = " + result); }
3.4 查询操作 MP提供了多种查询操作,包括根据id查询、批量查询、查询单条数据、查询列表、分页查询等操作。
1. selectById
方法定义:
1 2 3 4 5 6 T selectById (Serializable id) ;
测试用例:
1 2 3 4 5 6 @Test public void testSelectById () { User user = this .userMapper.selectById(2L ); System.out.println("result = " + user); }
2. selectBatchIds
方法定义:
1 2 3 4 5 6 List<T> selectBatchIds (@Param(Constants.COLLECTION) Collection<? extends Serializable> idList) ;
测试用例:
1 2 List<User> users = this .userMapper.selectBatchIds(Arrays.asList(2L , 3L , 10L ));
3. selectOne
方法定义:
1 2 3 4 5 6 T selectOne (@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) ;
测试用例:
1 2 3 4 5 QueryWrapper<User> wrapper = new QueryWrapper <User>(); wrapper.eq("name" , "李四" ); User user = this .userMapper.selectOne(wrapper);
4. selectCount
方法定义
1 2 3 4 5 6 Integer selectCount (@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) ;
测试用例:
1 2 3 4 5 6 7 8 9 @Test public void testSelectCount () { QueryWrapper<User> wrapper = new QueryWrapper <User>(); wrapper.gt("age" , 23 ); Integer count = this .userMapper.selectCount(wrapper); System.out.println("count = " + count); }
5. selectList
方法定义:
1 2 3 4 5 6 List<T> selectList (@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) ;
测试用例:
1 2 3 4 5 6 7 8 9 10 11 @Test public void testSelectList () {QueryWrapper<User> wrapper = new QueryWrapper <User>(); wrapper.gt("age" , 23 ); List<User> users = this .userMapper.selectList(wrapper); for (User user : users) { System.out.println("user = " + user); } }
6. selectPage
方法定义:
1 2 3 4 5 6 7 IPage<T> selectPage (IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper) ;
配置分页插件:
1 2 3 4 5 6 7 8 9 10 11 package cn.jyw.mp;@Configuration @MapperScan("cn.jyw.mp.mapper") public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor () { return new PaginationInterceptor (); } }
测试用例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Test public void testSelectPage () { QueryWrapper<User> wrapper = new QueryWrapper <User>(); wrapper.gt("age" , 20 ); Page<User> page = new Page <>(1 ,1 ); IPage<User> iPage = this .userMapper.selectPage(page, wrapper); System.out.println("数据总条数:" + iPage.getTotal()); System.out.println("总页数:" + iPage.getPages()); List<User> users = iPage.getRecords(); for (User user : users) { System.out.println("user = " + user); } }
3. 条件构造器 在MP中,Wrapper接口的实现类中AbstractWrapper和AbstractChainWrapper是重点实现
说明: QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类 用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件 注意: entity 生成的 where 条件与 使用各个 api 生成 的 where 条件没有任何关联行为
3.1 allEq 1 2 3 allEq(Map<R, V> params) allEq(Map<R, V> params, boolean null2IsNull) allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
个别参数说明: params : key 为数据库字段名, value 为字段值 null2IsNull : 为 true 则在 map 的 value 为 null 时调用 isNull 方法,为 false 时则忽略 value 为 null 的
例1: allEq({id:1,name:”老王”,age:null}) —> id = 1 and name = ‘老王’ and age is null
例2: allEq({id:1,name:”老王”,age:null}, false) —> id = 1 and name = ‘老王’
1 2 3 allEq(BiPredicate<R, V> filter, Map<R, V> params) allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
个别参数说明: filter : 过滤函数,是否允许字段传入比对条件中 params 与 null2IsNull : 同上
例1: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:”老王”,age:null}) —> name = ‘老王’ and age is null
例2: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:”老王”,age:null}, false) —> name = ‘老王’
测试 1 2 3 4 5 6 7 8 9 10 11 public void testWrapper () { QueryWrapper<User> wrapper = new QueryWrapper <>(); Map<String,Object> params = new HashMap <>(); params.put("name" , "曹操" ); params.put("age" , "20" ); params.put("password" , null ); List<User> users = this .userMapper.selectList(wrapper);
3.2 基本比较操作
字符
sql
eq
等于 =
ne
不等于 <>
gt
大于 >
ge
大于等于 >=
lt
小于 <
le
小于等于 <=
between
BETWEEN 值1 AND 值2
notBetween
NOT BETWEEN 值1 AND 值2
in
字段 IN (value.get(0), value.get(1), …)
notIn
字段 NOT IN (v0, v1, …)
测试 1 2 3 4 QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("password" , "123456" ).ge("age" , 20 ).in("name" , "李四" , "王五" , "赵六" ); List<User> users = this .userMapper.selectList(wrapper);
3.3 模糊查询
字符
sql
例子
like
LIKE ‘%值%’
like(“name”, “王”) —> name like ‘%王%’
notLike
NOT LIKE ‘%值%’
notLike(“name”, “王”) —> name not like ‘%王%’
likeLeft
LIKE ‘%值’
likeLeft(“name”, “王”) —> name like ‘%王’
likeRight
LIKE ‘值%’
likeRight(“name”, “王”) —> name like ‘王%’
测试 1 2 3 4 5 QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.like("name" , "曹" ); List<User> users = this .userMapper.selectList(wrapper);
3.4 排序
字符
sql
例子
orderBy
ORDER BY 字段, …
orderBy(true, true, “id”, “name”) —> order by id ASC,name ASC
orderByAsc
ORDER BY 字段, … ASC
orderByAsc(“id”, “name”) —> order by id ASC,name ASC
orderByDesc
ORDER BY 字段, … DESC
orderByDesc(“id”, “name”) —> order by id DESC,name DESC
测试 1 2 3 4 QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.orderByDesc("age" ); List<User> users = this .userMapper.selectList(wrapper);}
3.5 逻辑查询
字符
sql
例子
or
拼接 OR
主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用 or 则默认为使用 and 连接)
and
AND 嵌套
and(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) —> and (name = ‘李白’ and status <> ‘活着’)
测试 1 2 3 4 QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("name" ,"李四" ).or().eq("age" , 24 ); List<User> users = this .userMapper.selectList(wrapper);
3.6 select 在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。
1 2 3 4 QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.eq("name" , "李四" ).or().eq("age" , 24 ).select("id" , "name" , "age" ); List<User> users = this .userMapper.selectList(wrapper);
4. ActiveRecord ActiveRecord(简称AR)一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于 ActiveRecord 往往只能感叹其优雅
什么是ActiveRecord?
ActiveRecord也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。
ActiveRecord的主要思想是:
每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段 在类中都有相应的Field;
ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;
ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑;
4.1 开启AR之旅 在MP中,开启AR非常简单,只需要将实体对象继承Model即可。
1 2 3 4 5 6 7 8 9 10 11 @Data @NoArgsConstructor @AllArgsConstructor public class User extends Model <User> { private Long id; private String userName; private String password; private String name; private Integer age; private String email; }
4.2 基本的CRUD 根据主键查询 新增数据 更新操作 删除操作 根据条件查询
1 2 3 User user = new User ();user.setId(2L ); User user2 = user.selectById();
1 2 3 4 5 6 7 User user = new User ();user.setName("刘备" ); user.setAge(30 ); user.setPassword("123456" ); user.setUserName("liubei" ); user.setEmail("liubei@jyw.cn" ); boolean insert = user.insert();
1 2 3 4 User user = new User ();user.setId(8L ); user.setAge(35 ); boolean update = user.updateById();
1 2 3 User user = new User ();user.setId(7L ); boolean delete = user.deleteById();
1 2 3 4 User user = new User ();QueryWrapper<User> userQueryWrapper = new QueryWrapper <>(); userQueryWrapper.le("age" ,"20" ); List<User> users = user.selectList(userQueryWrapper);