一.准备工作
MyBatis-Plus的介绍大家可以自行去官网看:MyBatis-Plus 🚀 为简化开发而生
1.引入依赖
这里以Maven为例:
<!--springboot2-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.10.1</version>
</dependency>
<!--springboot3-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.10.1</version>
</dependency>
<!--MySQL驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
根据自己的springboot版本引入
2.配置文件
这方面与MyBatis是一样的,可以自行去以前的文章看:【快速入门】MyBatis-CSDN博客
配置日志:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.Mapper接口类
Mapper接口类要继承BaseMapper接口才可使用MP中通用的CRUD方法:
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
除了写@Mapper注解注入,我们还可以使用@MapperScan注解注入。@MapperScan注解写在项目的启动类上:
@SpringBootApplication
@MapperScan("com.example.project.mapper") // 指定 Mapper 接口包
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
当然,除了我们还可以使用xml文件的方式映射文件:
mybatis-plus:
mapper-locations: "classpath*:/mapper/**.xml"
二.实体类与表的关系
MP通过BaseMapper中的泛型的类型从数据库找对应的表,
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}
默认情况下:
1)表名:实体类的驼峰表示法转化成蛇形表示法,例如 UserInfo 变为 user_info;
2)字段名:根据实体类的属性名转化成蛇形表示法作为字段名,例如 userName 变为 user_flag;
3)主键默认为 id。
但是如果表名字段名或主键出现了不遵守规则的写法,MP也是为我们提供了三个注解来解决问题:
1)@TableName 注解
可以指定数据库名称
@Data
@TableName("user_info")
public class userInfo {
private Integer id;
private String username;
private String password;
}
如果不加会报这个错误:
2)@TableField 注解
可以指定字段名称
@Data
public class UserInfo {
private Integer id;
@TableField("user_name")
private String userName;
private String password;
}
3)@TableId 注解
可以指定主键,默认情况是id,但是我们写的是userId
@Data
public class UserInfo {
@TableId("id")
private Integer id;
private String username;
private String password;
}
三.条件构造器(Wrapper)
条件构造器(Wrapper)简单来说就是用来写SQL语句要执行的条件的。Mapper接口类继承BaseMapper后只能使用一些基本CRUD语句,没有办法完成复制的SQL语句,条件构造器就是用来解决这个问题的。
1.QueryWrapper
QueryWrapper可用于查询,更新,删除,但是不能用于插入。
使用起来也是相当简单,这里只举一个查询的例子大家就懂了。
SQL语句:
select id,username from user_info where age=18 and username like "%ang%"
对应的MP:
QueryWrapper<UserInfo> userInfoQueryWrapper=new QueryWrapper<>();
userInfoQueryWrapper.select("id","username")
.eq("age",18)
.like("username","ang");
List<UserInfo> userInfos=userInfoMapper.selectList(userInfoQueryWrapper);
至于这个eq和like是什么含义,还有什么其他的,请看MP官网,里面有详细的解释:
2.UpdateWrapper
我们除了使用上面的那种方法更新数据,还可以使用这个更新数据。
SQL语句:
update user_info set phone="114514" where id in (1,2)
对应的MP:
UpdateWrapper<UserInfo> updateWrapper=new UpdateWrapper<>();
updateWrapper.set("phone","114514")
.in("id",List.of(1,2));
userInfoMapper.update(updateWrapper);
3.Lambda Wrapper
通过上面的例子可以看到,我们在写代码的时候已经写死了字段名,万一修改了数据库的字段名,那么这些代码就全要重写了,成本比较大。
对此,MP为我们找到了解决办法,使用Lambda条件构造器。
对于QueryWrapper两种写法的对照:
//非Lambda写法
QueryWrapper<UserInfo> userInfoQueryWrapper=new QueryWrapper<>();
userInfoQueryWrapper.select("id","username")
.eq("age",18)
.like("username","ang");
List<UserInfo> userInfos=userInfoMapper.selectList(userInfoQueryWrapper);
//Lambda写法
QueryWrapper<UserInfo> userInfoQueryWrapper=new QueryWrapper<>();
userInfoQueryWrapper.lambda()
.select(UserInfo::getId,UserInfo::getUsername)
.eq(UserInfo::getAge,18);
List<UserInfo> userInfos=userInfoMapper.selectList(userInfoQueryWrapper);
UpdateWrapper写法与QueryWrapper写法类似:
UpdateWrapper<UserInfo> updateWrapper=new UpdateWrapper<>();
updateWrapper.lambda()
.set(UserInfo::getPhone,"114514")
.in(UserInfo::getId,List.of(1,2));
userInfoMapper.update(updateWrapper);
四.自定义SQL
在某些场景下,我们不仅仅满足于MP为我们提供的一些方法,还想自定义一些SQL。举个例子,我们想要通过某一个条件查询用户的id和username,但是这个条件会变化,我们一次次修改比较麻烦,这里我们就可以自定义一个SQL了。
下面的方法是写在Mapper接口类中的:
@Select("select id,username from user_info ${ew.customSqlSegment}")
List<UserInfo> selectUserByCondition(@Param(Constants.WRAPPER) QueryWrapper<UserInfo> queyWrapper);
说明:
1)版本要求:确保你的项目中使用的MP版本至少为 3.0.7,以支持自定义 SQL 功能。
2)参数命名:在自定义 SQL 时,传递 Wrapper 对象作为参数时,参数名必须为ew,或者使用注解 @Param(Constants.WRAPPER) 明确指定参数为 Wrapper 对象。
3)使用 ${ew.customSqlSegment}:在 SQL 语句中,使用 ${ew.customSqlSegment} 来引用 Wrapper 对象生成的 SQL 片段。
4)不支持基于 entity 的 where 语句:自定义 SQL 时,Wrapper 对象不会基于实体类自动生成 where 子句,你需要手动编写完整的 SQL 语句。
我们还可以正常传参数:
@Update("update user_info set age = age + #{addAge} ${ew.customSqlSegment}")
Integer updateById2(Integer addAge, @Param(Constants.WRAPPER) Wrapper<Userinfo> queyWrapper);