
SpringBoot2
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>SpringBoot3
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>MySQL
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>配置数据库,application.yml 文件:
# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver创建实体类 UserInfo:
实体类的属性名与表中的字段名一一对应
import lombok.Data;
import java.util.Date;
@Data
public class UserInfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}编写 Mapper 接口类:
MybatisPlus 提供了一个基础的 BaseMapper 接口,已经实现了单表的 CRUD,我们自定义的 Mapper只需要继承这个 BaseMapper,就无需自己实现单表 CRUD了,如下所示:
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
也可以在启动类上添加 @MapperScan,扫描 Mapper 文件夹,二选一即可。
在上面的程序中,MyBatis 是如何知道,我们要操作的是哪张表,表里有哪些字段呢?
我们来看下咱们 Mapper 的代码:
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}UserInfoMapper 在继承 BaseMapper 时,指定了一个泛型,这个 UserInfo 就是与数据库表相对应的实体类。
MyBatis-Plus 会根据这个实体类来推断表的信息。
默认情况下:
UserInfo -> user_infodeleteFlag -> delete_flagid那如果实体类和数据库不是按照上述规则定义的呢?MyBatis-Plus 也给我们提供了一下注解,让我们标识表的信息。
@TableName通过 @TableName 来标识实体类对应的表:
@Data
@TableName("user_info")
public class Userinfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}@TableField通过 @TableField 来标识对应的字段名:
@Data
public class Userinfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
@TableField("delete_flag") // 定义和数据库字段名相同
private Integer deleteflag;
private Date createTime;
private Date updateTime;
}@TableId通过 @TableId 来指定对应的主键:
@Data
public class Userinfo {
@TableId("id", type = IdType.AUTO)
private Integer userId;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteflag;
private Date createTime;
private Date updateTime;
}@TableId 注解就可以@TableId 指明对应的字段名常见的
IdType类型如下所示:
AUTOMySQL 的 AUTO_INCREMENT)。NONE(默认值)INPUTASSIGN_IDASSIGN_UUIDUUID 字符串作为主键。在配置文件中添加如下内容:
mybatis-plus:
configuration: # 配置打印 MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImplMyBatis-Plus 提供了一套强大的条件构造器 Wrapper,用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
以下是主要的 Wrapper 类及其功能:
AbstractWrapper:这是一个抽象基类,提供了所有 Wrapper 类共有的方法和属性。QueryWrapper:用于构造查询条件,在 AbstractWrapper 的基础上拓展了一个select方法,允许指定查询字段。UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。LambdaQueryWrapper:基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。LambdaUpdateWrapper:基于 Lambda 表达式的更新条件构造器,它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。QueryWrapper完成下述SQL查询:
SELECT id,username,password,age FROM user_info WHERE age = 18 AND username LIKE "%min%"测试代码:
@Test
void testQueryWrapper(){
QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>()
.select("id","username","password","age")
.eq("age",18)
.like("username", "min");
List<UserInfo> userInfos = userInfoMapper.selectList(userInfoQueryWrapper);
userInfos.forEach(System.out::println);
}💥注意:
默认情况下 Mybatis-Plus 会根据 @TableFiled 生成别名,当指定了 QueryWrapper 的 select 属性后就仅仅是属性值而没有了别名。查询出来的结果会对应不上。
完成下述SQL查询:
UPDATE user_info SET delete_flag=? WHERE age < 20测试代码:
@Test
void testUpdateByQueryWrapper(){
QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>()
.lt("age", 20);
UserInfo userInfo = new UserInfo();
userInfo.setDeleteFlag(1);
userInfoMapper.update(userInfo, userInfoQueryWrapper);
}lt:"less than" 的缩写,表示小于le:"less than or equal to" 的缩写,表示小于等于ge:"greater than or equal to" 的缩写,表示大于等于gt:"greater than" 的缩写,表示大于eq:"equals" 的缩写,表示等于ne:"not equals" 的缩写,表示不等于完成下述SQL查询:
DELETE FROM user_info WHERE age = 18测试代码:
@Test
void testDeleteByQueryWrapper(){
QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>()
.eq("age",18);
userInfoMapper.delete(userInfoQueryWrapper);
}对于更新,可以直接使用 UpdateWrapper,在不创建实体对象的情况下,直接设置更新字段和条件。
完成下述SQL查询:
UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)测试代码:
@Test
void testUpdateByUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
.set("delete_flag",0)
.set("age", 5)
.in("id", List.of(1,2,3));
userInfoMapper.update(updateWrapper);
}完成下述SQL查询:
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)测试代码:
@Test
void testUpdateBySQLUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
.setSql("age = age+10")
.in("id", List.of(1,2,3));
userInfoMapper.update(updateWrapper);
}QueryWrapper 和 UpdateWrapper 存在一个问题,就是需要写死字段名,如果字段名发生变更,可能会因为测试不到位酿成事故。
MyBatis-Plus 给我们提供了一种基于 Lambda 表达式的条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名,也提高了代码的可读性和可维护性。
接下来我们看下具体使用:
@Test
void testLambdaQueryWrapper(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
queryWrapper.lambda()
.select(UserInfo::getUsername, UserInfo::getPassword,UserInfo::getAge)
.eq(UserInfo::getUserId, 1);
userInfoMapper.selectList(queryWrapper).forEach(System.out::println);
}@Test
void testLambdUpdateByUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();
updateWrapper.lambda()
.set(UserInfo::getDeleteFlag, 0)
.set(UserInfo::getAge, 5)
.in(UserInfo::getUserId, List.of(1,2,3));
userInfoMapper.update(updateWrapper);
}在实际的开发中,MyBatis-Plus 提供的操作可能不能满足我们的实际需求,MyBatis-Plus 也提供了自定义 SQL 的功能,我们可以利用 Wrapper 构造查询条件,再结合 Mapper 编写 SQL。
📌 为了使用这一功能,mybatis-plus 版本不低于 3.0.7
完成下述SQL查询:
select id,username,password,age FROM user_info WHERE username = "admin"Mapper:
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
@Select("select id,username,password,age FROM user_info ${ew.customSqlSegment}")
List<UserInfo> queryUserByCustom(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
}测试代码:
@Test
void testQueryUserByCustom(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.eq("username","admin");
userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
}💥注意事项:
ew,或者使用注解@Param(Constants.WRAPPER) 明确指定参数为 Wrapper 对象。${ew.customSqlSegment} 来引用 Wrapper 对象生成的 SQL 片段。MyBatis-Plus 在 MyBatis 的基础上只做增强不做改变,所以也支持XML的实现方式。
上述功能也可以使用XML的方式完成:
mybatis-plus:
mapper-locations: "classpath*:/mapper/**.xml" # Mapper.xml2. 定义方法
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
List<UserInfo> queryUserByCustom2(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
}3. 编写XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bite.mybatis.plus.mapper.UserInfoMapper">
<select id="queryUserByCustom2">
select id,username,password,age FROM user_info ${ew.customSqlSegment}
</select>
</mapper>4. 测试
@Test
void testQueryUserByCustom2(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.eq("username","admin");
userInfoMapper.queryUserByCustom2(queryWrapper).forEach(System.out::println);
}完成下述 SQL 查询:
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)Mapper:
@Update("UPDATE user_info SET age = age+ #{addAge} ${ew.customSqlSegment}")
void updateUserByCustom(@Param("addAge") int addAge, @Param("ew") Wrapper<UserInfo> wrapper);测试代码:
@Test
void updateUserByCustom(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.in("id",List.of(1,2,3));
userInfoMapper.updateUserByCustom(10, queryWrapper);原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。