4. Mybatis-plus
ORM介绍
- ORM(Object Relational Mapping,对象关系映射)是为了解决面向对象与关系数据库存在的互不匹配现象的一种技术。
- ORM通过使用描述对象和数据库之间映射的元数据将程序中的对象自动持久化到关系数据库中。
- ORM框架的本质是简化编程中操作数据库的编码。
MyBatis-Plus介绍
- MyBatis是一款优秀的数据持久层ORM框架,被广泛地应用于应用系统
- MyBatis能够非常灵活地实现动态SQL,可以使用XML或注解来配置和映射原生信息,能够轻松地将Java的POJO(Plain OrdinaryJava Object,普通的Java对象)与数据库中的表和字段进行映射关联。
- MyBatis-Plus是一个 MyBatis 的增强工具,在 MyBatis 的基础上做了增强简化了开发。
MybatisPlus 依赖添加
<!--Mybatis依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!--Mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<!--数据库连接池 druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.20</version>
</dependency>
全局配置
application.properties
# 配置数据库相关信息。
# 导入druid连接池
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 使用mysql jdbc驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 数据库配置
spring.datasource.url=jdbc:mysql://locahost:3306/mydb?usessL=false
spring.datasource.username=root
spring.datasource.password=123456
# 指定日志输出格式
mybatis-plus.configuration.1og-impl=org.apache.ibatis.logging.stdout.StdOutImpl
添加@MapperScan注解
默认之后对于数据库的操作会放到哪一个包里,扫描那个包
@SpringBootApplication
@MapperScan("com.xx.mapper")// mapper包路径
public class SpringBootAppDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAppDemoApplication.class, args);
}
}
MyBatis CRUD
常用MyBatis注解
注解 | 功能 |
---|---|
@Insert | 实现插入操作 |
@Update | 实现更新操作 |
@Delete | 实现删除操作 |
@Select | 实现查询操作 |
@Result | 实现结果集封装,用于将数据库查询结果映射到Java对象的属性中 |
@Results | 可以与@Result一起使用,封装多个结果集 |
@One | 实现一对一结果集封装,用于结果集中的单个实体映射 |
@Many | 实现一对多结果集封装,用于结果集中的集合属性映射 |
UserMapper
@Mapper
public interface UserMapper {
// 查询所有用户
@Select("select * from user")
public List<User> list();
// 增加一个用户,返回插入用户的成功条数
@Insert("insert into user values (#{id},#{name},#{age})")
public int insert(User user);
// 删除
@Delete("delete from user where id=#{id}")
public int delete(int id);
// 修改
@Update("update user set name=#{name} ,age=#{age} where id=#{id}")
public int update(User user);
// 查询
@Select("select * from user where id=#{id}")
public User find(int id);
}
MybatisController
@RestController
public class MybatisController {
// 自动注入UserMapper
@Autowired
private UserMapper userMapper;
@GetMapping("/user_list")
public List query(){
return userMapper.list();
}
@PostMapping("/user")
public String save(User user){
int i = userMapper.insert(user);
return i > 0?"插入成功":"插入失败";
}
@DeleteMapping("/user")
public String delete(int id){
int i = userMapper.delete(id);
return i > 0?"删除成功":"删除失败";
}
@PutMapping("/user")
public String update(User user){
int i = userMapper.update(user);
return i>0?"修改成功":"修改失败";
}
@GetMapping("/user")
public User find(int id){
return userMapper.find(id);
}
}
User entity
public class User {
private int id;
private String name;
private Integer age;
// set...get...
}
使用mybatisPlus简化mapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
继承了BaseMapper<User>
类型后,就不需要再手写简单的增删改查sql语句,父方法很全
更多注解方法可以看MyBatis-Plus (baomidou.com)
- 主键回显:@TableId()
- 主键自增:@TableId(type=IdType.AUTO)
- 字段名重新映射:@TableName()
- ...
MyBatis CRUD高级
多表查询
1. 创建实体
实体的字段需要和数据库上列名匹配
@TableName("goods")
public class Goods {
@TableId(type= IdType.AUTO)
private int id;
private String name;
private double price;
@TableField(exist = false)//描述货物的订单,表示不存在,忽略这个字端上的操作,导入需要自行编写
private List<Order> orders;
// set ... get ...
}
@TableName("order")
public class Order {
@TableId(type= IdType.AUTO)
private int id;
private int good_id;
private int amount;
@TableField(exist = false)//表示不存在,忽略这个字端上的操作,导入需要自行编写
// set ... get ...
}
2. 创建Mapper
下面的代码实现了对于从goods货物表到order订单表的一对多关系查询
注意:表名order和MySQL关键字冲突,需要加上单引号
@Mapper
public interface GoodsMapper extends BaseMapper<Goods> {
@Select("select * from goods") // 没有处理完全,连表没做
public List<Goods> selectGoods();
@Select("select * from goods where id=#{id}") //该方法可不写,使用继承来的selectById做平替换
public Goods selectGoodsById(int id);
@Select("select * from goods")
@Results( // Result 注意单复数,使用后必须自己完成映射
{
@Result(column = "id",property = "id"), // column表示表里的数据列,property表示结构体里的字段
@Result(column = "name",property = "name"),
@Result(column = "price",property = "price"),
@Result(column = "id",property = "orders",javaType = List.class, //javaType告诉返回值是一个列表类型
many = @Many(select = "com.example.springbootappdemo.mapper.OrderMapper.selectByGoodId")
// @Many表示一对多的关系
)
}
)
public List<Goods> selectGoodsAndOrder();
}
下面实现了对于从order订单表到goods货物表的一对一关系查询
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
@Select("select * from `order` where good_id=#{good_id}")
List<Order> selectByGoodId(int good_id);
// order 是关键词,加``防止出问题
@Select("select * from `order`")
@Results( // Result 注意单复数,使用后必须自己完成映射
{
@Result(column = "id",property = "id"), // column表示表里的数据列,property表示结构体里的字段
@Result(column = "amount",property = "amount"),
@Result(column = "good_id",property = "good_id"),
@Result(column = "good_id",property = "good",javaType = Goods.class, //javaType告诉返回值是一个列表类型
one = @One(select = "com.example.springbootappdemo.mapper.GoodsMapper.selectGoodsById")
// @Many表示一对一的关系
)
}
)
public List<Order> selectOrderAndGoods();
}
条件查询
MyBatis 还有一些自带的查询方法可使用
下面是一个实例
// 条件查询
@GetMapping("/user/find")
public List<User> findByCond(String name){
QueryWrapper<User> queueWarpper = new QueryWrapper<>();
queueWarpper.eq("name",name);
return userMapper.selectList(queueWarpper);
}
分页查询
配置分页查询
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor paginationInterceptor(){
// 分页拦截器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 配置数据库类型
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
// 拦截器注册
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
}
分页查询代码
// 分页查询
@GetMapping("/user/page")
public IPage findPage(int page,int size){
Page<User> config = new Page<>(page,size);
IPage iPage = userMapper.selectPage(config,null);
return iPage;
}
XML 映射文件
XML映射文件
- XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
- XML映射文件的namespace属性为Mapper接口全限定名一致。
- XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
com/example/springbootappdemo/mapper/userMapper.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.example.springbootappdemo.mapper.UserMapper">
<!-- findByName -->
<!--id:方法名,resultType:结果类型-->
<select id="findByName" resultType="com.example.springbootappdemo.entity.User">
select * from `user` where `name` = #{name}
</select>
</mapper>
@Mapper
public interface UserMapper extends BaseMapper<User> {
public User findByName(String name);
}
如果上面三个规范都满足,就可以自动用上上面的sql语句
MybatisX plugin
动态SQL
<if> <where> <set>
用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SOL。
<select id="searchList" resultType="com.example.springbootappdemo.entity.User">
select *
from `user`
where
<if test="name != null">
name like concat('%',#{name},'%')
</if>
<if test="ageL != 0 and ageR != 0">
and age between #{ageL} and #{ageR}
</if>
order by age desc
</select>
上面代码通过<if>
来判断是否要拼接查询语句,但是如果有and在最前就会报错(多余),使用<where>
包装后可以解决这个问题
<select id="searchList" resultType="com.example.springbootappdemo.entity.User">
select *
from `user`
<where>
<if test="name != null">
name like concat('%',#{name},'%')
</if>
<if test="ageL != 0 and ageR != 0">
and age between #{ageL} and #{ageR}
</if>
</where>
order by age desc
</select>
- 动态决定是否增加where字段
- 同台决定是否增加and、or
public List<User> searchList(@Param("name") String name, @Param("ageL") int ageL, @Param("ageR") int ageR);
@Param("name")用于指定名字,去掉后会报错,显示name不存在,原因不明
更新示例
// 修改
@Update("update user set name=#{name} ,age=#{age} where id=#{id}")
public int update(User user);
如果参数没有传递age、name等参数,就会默认设置为null,更新后会全部影响数据库的信息。所以为了只修改其中一部分的数据,可以使用动态更新
<update id="updateDetail">
update user
<set>
<if test="name != null">name = #{name},</if>
<if test="name != null">age = #{age}</if>
</set>
where id = #{id}
</update>
- 可以自动去掉多余的逗号
<for-each>
<!--
collection:遍历的集台
item:遍历出来的元素
separator:分隔符
open:遍历开始前拼接的SQL片段
close:遍历结束后拼接的SQL片段
-->
<!--最后拼接组成的是形如 (1,2,3)-->
<delete id="deleteByIds">
delete from user
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
public int deleteByIds(@Param("ids") List<Integer> ids);
同样的问题不知道为什么不给
@Param("ids")
就会报错
<include>
<sql id = "commonSelect">
select
*
from `user`
</sql>
<select id="findByName" resultType="com.example.springbootappdemo.entity.User">
<include refid="commonSelect"/>
where `name` = #{name}
</select>
转载自:https://juejin.cn/post/7381396887189045287