注解
@TableName
表名注解,当数据库中的表名和实体类名之间不能完全匹配时,需要使用这个注解进行绑定。
如:数据库表中的数据库表名为t_student
,而实体类的类名为:Student
,则需要在该类上增加注解:
1 |
全局设置数据库表前缀
当数据库表中的所有表名前有前缀时,需要每次指定@TableName
注解,很麻烦,需要使用全局配置:
1 | mybatis-plus: |
@TableId
主键注解,当数据库中的主键和实体类中主键属性不同时,使用这个注解进行绑定。
如:数据库表中的主键是id
,而实体类中的属性值是stuId
,那么就在实体类主键属性上加上注解
1 | public class Student { |
IdType
@TableId
注解还有一个属性配置是主键的主键类型,具体可选值如下,默认值为:IdType.NONE
值 | 描述 |
---|---|
AUTO | 数据库自增 |
INPUT | 自行输入 |
ID_WORKER | 分布式全局唯一ID 长整型类型 |
UUID | 32位UUID字符串 |
NONE | 无状态(默认) |
ID_WORKER_STR | 分布式全局唯一ID 字符串类型 |
全局设置设置注解策略
设置主键策略,默认值:ID_WORKER
1 | mybatis-plus: |
全局设置驼峰功能
mybatisPlus 有一个全局的配置策略,可以实现数据库表中的列名字段是下划线分割,自动对应实体类中驼峰名:
如:数据库中的stu_address
字段与实体类中的stuAddress
属性字段相对应。
1 | mybatis-plus: |
在 Springboot 中,可以通过设置map-underscore-to-camel-case
属性为 true 来开启驼峰功能。因此 mybatisPlus 也继承了这种配置,默认为 true:
1 | mybatis-plus: |
@TableField
value
当显示配置的时候,则按设置的值为准。
exist
标识该字段是数据库表字段,当实体类中有属性字段不在数据库表中的时候,就需要在数据库操作时忽略这些字段,因此可以配置exist=false
属性配置,如果不配置,默认为:true
BaseMapper
BaseMapper 接口是专门用来进行通用增删改查的接口,通过指定泛型可以对数据实体对象进行通用的CIUD操作,大致可以分为四类:
Insert
int insert(T entity)
insert 方法会将实体对象中的非空属性值映射到数据库,进行插入操作,也就是说有多少非空属性,执行的SQL语句中才插入多少,和 mybatis 中的 insertSeletive 一样,有值才操作。
亮点:
插入成功默认返回主键,mybatis Plus 插入数据之后,实体类中的主键会返回给实体类,相比 mybatis 原生的默认不返回要很多繁琐的配置:
1 | <insert id="insert" useGeneratedKeys="true" keyProperty="stuId" parameterType="org.woodwhales.king.Student"> |
其中:keyProperty
中配置的是实体类中的属性字段,用来接收数据库表返回的主键值。
Update
根据主键更新
int updateById(T entity)
带条件的更新
int update(T entity, Wrapper<T> updateWrapper)
如:更新姓名为Tom
且年龄为 28 的学生数据:
1 | LambdaQueryWrapper<Student> lambdaQueryWrapper = new QueryWrapper<Student>().lambda() |
SQL脚本执行日志:
1 | ==> Preparing: UPDATE student SET name=?, age=?, email=? WHERE name = ? AND age = ? |
Select
Delete
条件构造器
EntityWapper
注意:条件构造器中使用的是数据列名,而不是实体类对象属性。
分页查询(带条件)
对于条件构造器的编写,可以使用最原始写法:
1 | QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); |
也可以使用QueryWrapper<User>().lambda()
这样类似于 JDK1.8 的lambda表达式
编写条件构造器,下文中均采用此写法。
例:查询数据库中 student 表(Student
实体类)中的所有姓名为Tom
且年龄在10-20 岁之间的分页数据,当前页为 1,每页显示数为 2
1 | IPage<Student> pager = studentMapper.selectPage(new Page<Student>(1, 2), |
SQL脚本执行日志:
1 | ==> Preparing: SELECT id,name,age,email FROM student WHERE name = ? AND age BETWEEN ? AND ? LIMIT ?,? |
注意:上面代码查询出来的对象pager
中的total
和pages
总是为 0 ,解决办法:编写一个配置类,自定义一个分页插件PaginationInterceptor
配置到 spring 中即可:
1 | import org.springframework.context.annotation.Bean; |
上述代码中:只需要返回new PaginationInterceptor()
即可使得selectPage
返回对象中有数据总记录数。
带条件的查询-并且
查询数据库中 student 表(Student
实体类)中的所有邮箱名字含有woodwhale
且年龄在10-20 岁之间的所有数据:
1 | List<Student> studentList = studentMapper.selectList(new QueryWrapper<Student>() |
SQL脚本执行日志:
1 | ==> Preparing: SELECT id,name,age,email FROM student WHERE email LIKE ? AND age BETWEEN ? AND ? |
带条件的查询-或者
1 | IPage<Student> pager = studentMapper.selectPage(new Page<Student>(1, 2), |
注意:or()
中可以传参一个布尔表达式,当条件为false
时,或者作用失效,后面的条件会与前面的条件形成并且的关系。引用官方的解释:
主动调用
or
表示紧接着下一个方法不是用and
连接!(不调用or
则默认为使用and
连接)
SQL脚本执行日志:
1 | ==> Preparing: SELECT COUNT(1) FROM student WHERE name = ? AND age BETWEEN ? AND ? OR email LIKE ? |
查询结果排序
orderBy(boolean condition, boolean isAsc, R... columns)
对查询的结果进行降序排列(isAsc
设置成了false
)
1 | List<Student> studentList = userMapper.selectList(Wrappers.<Student>query().orderBy(true, false, "age")); |
SQL 脚本执行日志:
1 | ==> Preparing: SELECT id,name,age,email FROM student ORDER BY age DESC |
mybatis Plus 提供了更加便捷的方法:
降序排序
orderByDesc(R column)
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
升序排序
orderByAsc(R column)
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
领域模式
ActiveRecord
必须存在对应的原始mapper
并继承baseMapper
并且可以使用的前提下,才能使用此 AR 模式。
使用方法
实体类对象继承 Model
抽象类即可。
1 |
|
对数据的增删改查操作,直接操作自己即可。
1 | Student student = Student.builder().id(null).name("adc").age(20).email("ss@q.com").build(); |
条件查询
领域模式下查询主键的方法,有参数传入时以传入为准,无参数时以对象为准。当对象没有主键时,会报com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: selectById primaryKey is null.
异常,删除主键的方法同理,另外删除逻辑上不存在的数据也是返回成功。
1 | Student student = Student.builder().id(5L).build(); |
SQL脚本执行日志:
1 | ==> Preparing: SELECT id,name,age,email FROM student WHERE id=? |
分页查询
分页返回的数据对象是IPage
,从IPage
可以获取相应的总记录数,记录,当前页,每页数。
1 | IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper) |
代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,MyBatis-Plus 的代码生成器比 Mybatis 原生的代码生成器强大的地方在于,能够快速生成通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
以下代码生成器中开启了lombok
,sprigboot-web
,swagger2
,freemarker
,因此需要添加依赖:
1 | <dependencies> |
最佳实践
1 | import java.util.ArrayList; |
生成的项目结构如下:
插件
攻击 SQL 阻断解析器
作用!阻止恶意的全表更新删除
1 |
|
性能分析插件
该插件只用于开发环境,不建议生产环境使用。
1 |
|
乐观锁插件
目的:当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁的实现思路:
- 取出记录时,获取当前
version
- 更新时,带上这个
version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果
version
不对,就更新失败
插件使用步骤:
- 将插件注入spring 框架:
1 |
|
- 使用注解
@Version
注解实体字段(必要步骤)
1 |
|
特别说明:
- 支持的数据类型只有:
int
,Integer
,long
,Long
,Date
,Timestamp
,LocalDateTime
- 整数类型下
newVersion = oldVersion + 1
newVersion
会回写到entity
中- 仅支持
updateById(id)
与update(entity, wrapper)
方法 - 在
update(entity, wrapper)
方法下, wrapper不能复用!
逻辑删除插件
首先指定逻辑删除字段在数据库表中的取值:
1 | mybatis-plus: |
将插件注入spring中:
1 | import com.baomidou.mybatisplus.core.injector.ISqlInjector; |
实体类字段上加上@TableLogic
注解
1 |
|
使用 Mybatis-Plus 自带方法删除和查找都会附带逻辑删除功能(自己写的xml
不会)
MybatisX插件(IDEA插件)
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx
搜索并安装。
插件功能:Java 与 XML 调回跳转,Mapper 方法自动生成 XML。