数据库文件
https://www.yuque.com/yiquanchaoren-dvwhg/javassm/gk0g4m?inner=nwEE8
Mybatis Plus使用流程
导入依赖:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>3.4.3.2</version></dependency>
实现映射:
1.对象名称与表的名称一一对应。
2.对象的属性与表中的字段一一对应。
注解:
1. `**@TableName**`**表名注解**
| 属性 | 类型 | 必须指定 | 默认值 | 描述 |
|---|---|---|---|---|
| value | String | 否 | “” | 表名 |
| schema | String | 否 | “” | schema |
| keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值) |
| resultMap | String | 否 | “” | xml 中 resultMap 的 id |
| autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入) |
| excludeProperty | String[] | 否 | {} | 需要排除的属性名(@since 3.3.1) |
2. `**@TableId**`**主键注解**
| 属性 | 类型 | 必须指定 | 默认值 | 描述 |
|---|---|---|---|---|
| value | String | 否 | “” | 主键字段名 |
| type | Enum | 否 | IdType.NONE | 主键类型 |
3. `**@TableField**`**字段注解,非主键**
| 属性 | 类型 | 必须指定 | 默认值 | 描述 |
|---|---|---|---|---|
| value | String | 否 | “” | 数据库字段名 |
| el | String | 否 | “” | 映射为原生 #{ … } 逻辑,相当于写在 xml 里的 #{ … } 部分 |
| exist | boolean | 否 | true | 是否为数据库表字段 |
| condition | String | 否 | “” | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s},参考(opens new window) |
| update | String | 否 | “” | 字段 update set 部分注入, 例如:update=”%s+1”:表示更新时会set version=version+1(该属性优先级高于 el 属性) |
代码:
@Data@Accessors(chain = true)/*1. 将对象与表进行关联规则:若表名与对象名一致,名称可以省略属性名与字段名一致,注解可以省略*/@TableName("demo_user")@Component//序列化接口的作用:保证对象网络传输有效性public class User implements Serializable {//2. Id代表主键,主键自增/非空/UUID---生成唯一编号@TableId(type = IdType.AUTO, value = "id")private Integer id;//3. 标识属性与字段的映射@TableField("name")private String name;@TableField("age")private Integer age;@TableField("sex")private String sex;}
继承特定接口,实现CRUD操作
Myatis Plus内部准备了一个BaseMapper接口,BamsMapper接口将几乎所有的表操作进行了编写,用户只需要用自己编写的接口继承,即可使用BaseMapper接口所提供所有功能。
规则:
继承BaseMapper接口必须添加泛型对象,否则映射表报错
自己创建的接口不要与接口方法重名
代码:
@Mapper/*继承BaseMapper接口必须添加泛型对象,否则映射表报错自己创建的接口不要与接口方法重名*/public interface UserMapper extends BaseMapper<User> {}
在yml中配置Mybatis Plus
mybatis-plus:#别名type-aliases-package: com.jt.pojo#指定映射文件的位置mapper-locations: classpath:mappers/*.xml#开启驼峰规则configuration:map-underscore-to-camel-case: true
测试
其中查询方法UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件。
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;/*插入操作:新增数据:(name="阿富汗",age=40,sex="厉害")*/@Testpublic void insert() {User user = new User().setName("阿富汗").setAge(40).setSex("厉害");try {userMapper.insert(user);System.out.println("成功");} catch (Exception e) {System.out.println("失败");}}/*查询*/@Testpublic void select() {try {List<User> users = userMapper.selectList(null);System.out.println("成功");for (User user : users) {System.out.println(user);}} catch (Exception e) {System.out.println("失败");}}}
Mybatis Plus的操作原理
例如:
@Testpublic void insert() {User user = new User().setName("阿富汗").setAge(40).setSex("厉害");try {userMapper.insert(user);System.out.println("成功");} catch (Exception e) {System.out.println("失败");}}
上述代码相当于SQL语句:insert into 表名(字段名称) values(属性的值)
其核心为:Mybatis Plus将常规的操作进行了抽取,并采用公共的接口进行了定义,然后只需要通过接收用户传递的参数进行动态的SQL拼接。
理论流程
- 用户调用接口方法,完成CRUD操作。
userMapper.insert(user); - Mybatis Plus根据用户传递的对象使用反射获取User类。
Class userClass = user.getClass(); - 根据获取的User类,使用反射获取User类的指定注解,
_TableName _tableName = (_TableName_) userClass.getAnnotation(_TableName_._class_); - 通过获取的注解来动态的获取注解中的参数,从中获取数据表的表名。
String name = tableName.value(); - 通过User类可以获取User类的属性,
Field[] fields = userClass.getDeclaredFields();获取到User类的属性后就可以使用反射获取User类属性的注解,Field[] fields = userClass.getDeclaredFields();因为属性为封装后的私有属性,所以需要使用暴力反射。获取到属性的注解后即可得到表中的字段名。 - 将获取到的表名与字段名与用户传递的参数进行SQL拼接,
insert into demo_user(id,age,name,sex) value (user.getId()…)。 - 将拼接的SQL交由Mybatis进行执行,以实现CRUD操作。
代码实现:
//根据对象获取User类Class userClass = user.getClass();//根据User类获取User类注解TableName tableName = (TableName) userClass.getAnnotation(TableName.class);//根据User类的注解获取表名String name = tableName.value();//根据User类获取属性名称,因为属性私有,所以使用暴力反射Field[] fields = userClass.getDeclaredFields();String[] tableFields = new String[fields.length];//根据属性名获取注解for (int i = 0; i < fields.length; i++) {TableField annotation = fields[i].getAnnotation(TableField.class);//根据注解或取字段名tableFields[i] = annotation.value();}
使用Mybatis Plus进行查询操作
主键查询,使用id进行查询
查询所用方法selectById(int id);参数为需要查询的信息的主键id。
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//查询id为231的信息,主键查询@Testpublic void selectById() {int id = 232;User user = userMapper.selectById(id);System.out.println(user);}}
使用条件构造器进行全部数据查询
查询方法:userMapper.selectList(QueryWrapper queryWrapper);其中queryWapper为条件构造器,可为null,为null将会查询表中所有数据。
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;/*查询*/@Testpublic void select() {try {List<User> users = userMapper.selectList(null);System.out.println("成功");for (User user : users) {System.out.println(user);}} catch (Exception e) {System.out.println("失败");}}}
条件构造器—-对象封装
查询name=”小乔”,sex=“女”的信息。
QueryWrapper为条件构造器,用于生成 where 条件。
流程:
- 使用对象封装数据
User user = new User().setName(“小乔”).setSex(“女”);
构建条件触发器并使用,使用对象中不为null的属性作为where查询条件,默认链接符为and
where name = '小乔' and sex = '女'
此时参数即为封装的对象。
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//查询name="小乔",sex=“女”@Testpublic void selectByNameAndBySex() {QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(new User().setName("小乔").setSex("女"));//根据条件构造器进行查询List<User> users = userMapper.selectList(userQueryWrapper);for (User user : users) {System.out.println(user);}}}
条件构造器—-逻辑运算符查询
| 普通运算符 | MybatisPlus中的运算符 | 例子 |
|---|---|---|
| = | eq | eq(“name”, “老王”)—->name = ‘老王’ |
| > | gt | gt(“age”, 18)—->age > 18 |
| < | lt | lt(“age”, 18)—->age < 18 |
| >= | ge | ge(“age”, 18)—->age >= 18 |
| <= | le | le(“age”, 18)—->age <= 18 |
| != | ne | ne(“name”, “老王”)—->name <> ‘老王’ |
eq(R column, Object val),lt(R column, Object val)column为字段名,val为查询所需要的参数。
查询name=”小乔”,sex=“女”的信息,查询age<18,name = “女“
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;@Test//查询name="小乔",sex=“女”public void selectAgeAndSex() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("name", "小乔").eq("sex", "女");List<User> users = userMapper.selectList(queryWrapper);for (User user : users) {System.out.println(user);}QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();userQueryWrapper.eq("sex", "女").lt("age", 18);List<User> users1 = userMapper.selectList(userQueryWrapper);for (User user : users1) {System.out.println(user);}}}
条件构造器—-Like关键字
like(R column, Object val),column为字段名,val为模糊查询所需要的参数。
- 例:
like("name", "王")—->name like '%王%'
查询name中包含“君”字的数据
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//查询name中包含“君”字的数据@Testpublic void selectLike() {QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();userQueryWrapper.like("name", "君");List<User> users = userMapper.selectList(userQueryWrapper);for (User user : users) {System.out.println(user);}}}
条件构造器—-排序
- orderByAsc升序排序:
orderByAsc(R... columns),参数为需要排序的字段名。
例: orderByAsc("id", "name")—->order by id ASC,name ASC
- orderByDesc降序排序:
orderByDesc(R... columns),参数为需要排序的字段名。
例:orderByDesc("id", "name")—->order by id DESC,name DESC
- orderBy:
orderBy(boolean condition, boolean isAsc, R... columns),condition字段表示是否拼接where条件,isAsc表示是否使用升序排序,columns为需要排序的字段。
例:orderBy(true, true, "id", "name")—->order by id ASC,name ASC
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//查询性别为女的信息,并按年龄降序排序@Testpublic void selectOrderBy() {QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();userQueryWrapper.eq("sex", "女").orderByDesc("age");List<User> users = userMapper.selectList(userQueryWrapper);for (User user : users) {System.out.println(user);}}}
条件构造器—-动态SQL
当我们进行条件查询时,又是需要先进行判断,判断字段值是否存在或者是否符合条件,当不存在或者不符合条件时就会出错或查询不到数据。此时需要进行动态的where条件拼接,使用条件构造器中的各种方法提供的condition参数就可以实现是否拼接SQL。
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;/*动态SQL若有值则进行where条件拼接,为null则不进行where条件拼接。使用condition参数*/@Testpublic void selectIsNull() {String name = "貂蝉";int age = 0;boolean nameFlag = name != null;boolean ageFlag = age != 0;QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq(nameFlag, "name", name).eq(ageFlag, "age", age);List<User> users = userMapper.selectList(queryWrapper);System.out.println(users);}}
条件构造器—-in关键字
in(R column, Collection<?> value),value为查询条件的参数。
in关键字的两种使用方式:
- IN (value.get(0), value.get(1), …)
in("age",{1,2,3})—->age in (1,2,3)
- IN (v0, v1, …)
in("age", 1, 2, 3)—->age in (1,2,3)
查询id=1,4,5,6·····的数据
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//查询id=1,4,5,6·····的数据@Testpublic void selectIn() {//1.方式1QueryWrapper<User> idQueryWrapper = new QueryWrapper<User>().in("id", 1, 4, 5, 6);List<User> users = userMapper.selectList(idQueryWrapper);for (User user : users) {System.out.println(user);}//2.方式2ArrayList<Integer> ids = new ArrayList<>();ids.add(1);ids.add(4);ids.add(5);ids.add(6);QueryWrapper<User> idQueryWrapper1 = new QueryWrapper<User>().in("id", ids);List<User> users1 = userMapper.selectList(idQueryWrapper1);for (User user : users1) {System.out.println(user);}}}
条件构造器—-查询第一个字段的记录
根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
查询性别为男的数据,只查询id字段
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//查询性别为男的数据,只查询id字段@Testpublic void selectObjs() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("sex", "男");//根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值List<Object> ids = userMapper.selectObjs(queryWrapper);System.out.println(ids);}}
Mybatis Plus更新操作
使用主键进行更新
int updateById(@Param(Constants.ENTITY) T entity);方法为updateById()其中参数为实体对象,即set条件。
将id为234的数据改为”车臣“,age=10,sex=男。
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//将id为234的数据改为”车臣“,age=10,sex=男@Testpublic void testUpdate() {User user = new User().setId(234).setName("车臣").setAge(10).setSex("男");userMapper.updateById(user);}}
根据条件选择器条件进行更新
方法为update(),int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);有两个参数,第一个参数为set条件,第二个参数为条件选择器,根据条件选择器的where条件进行数据更新。
将name=”阿富汗“ 改为 塔利班,age=40,sex=”911”
代码实现:
@SpringBootTestpublic class TestMP {@Autowiredprivate UserMapper userMapper;//将name=”阿富汗“ 改为 塔利班,age=40,sex="9/11"@Testpublic void testUpdate1() {User user = new User().setName("塔利班").setAge(40).setSex("911");UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.eq("name", "阿富汗");/*update(arg1,arg2)arg1为set即更新后的数据arg2为条件构造器,即where条件*/userMapper.update(user, wrapper);}}
Mybatis Plus分页查询
Mybatis Plus分页查询需要定义分页对象,IPage<User> page=new Page<>();其中Page<>需要传递两个参数,第一个参数为需要查询的记录起始条数,第二个参数为需要查询的记录条数。例如使用sql语句进行分页查询时,第一个参数为查询的起始记录,第二个参数为查询的记录数量。
使用selectPage()进行分页查询,其参数为分页对象。
代码实现:
pojo
@Data@Accessors(chain = true)@TableName("user")public class User extends BasePojo {@TableId(type = IdType.AUTO)private Integer id;private String username;private String password;private String phone;private String email;private Boolean status;}
PageResult类
@Data@Accessors(chain = true)public class PageResult implements Serializable {private String query;private Integer pageNum;private Integer pageSize;private Long total;//总记录数private Object rows;//查询得到的记录列表}
service类
@Overridepublic PageResult getUserList(PageResult pageResult) {//分页对象IPage<User> page = new Page<>(pageResult.getPageNum(), pageResult.getPageSize());//条件构造器QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq(StringUtils.hasLength(pageResult.getQuery()), "username", pageResult.getQuery());page = userMapper.selectPage(page, queryWrapper);pageResult.setTotal(page.getTotal()).setRows(page.getRecords());return pageResult;}
Mybatis Plus自动填充功能
Mybatis Plus可以对数据表中的属性进行自动填充,例如入库时间,更新时间等
使用Mybatis Plus的自动填充功能需要在pojo中需要使用自动填充的字段索映射的属性中添加注解,@TableField(fill = FieldFill.INSERT),其中fill有4个属性分别为DEFAULT(默认不处理),INSERT(插入填充字段),UPDATE(更新填充字段),INSERT_UPDATE(插入和更新填充字段)。
@Data@Accessors(chain=true)public class BasePojo implements Serializable{@TableField(fill = FieldFill.INSERT)private Date created; //表示入库时需要赋值@TableField(fill = FieldFill.INSERT_UPDATE)private Date updated; //表示入库/更新时赋值.}
定义配置类,实现**MetaObjectHandler**接口,使得@TableField属性中的配置生效。
@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {//metaObject代表默认配置this.setFieldValByName("created", new Date(), metaObject);//表示created字段将会自动填充this.setFieldValByName("updated", new Date(), metaObject);//表示updated字段将会自动填充}@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updated", new Date(), metaObject);}}
