Mybatis-plus随笔

首先

首先Mybatis-plus是对Mybatis的增强,他能够无缝衔接Mybatis,也就是说即使我使用了BaseMapper,但是我还是可以写属于自己的mapper函数,还是可以用xml对应实现,这并不冲突

pom依赖

首先pom依赖,这里springboot版本过高会不兼容

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.note</groupId>
    <artifactId>note</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>note</name>
    <description>note</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.4.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

mapper

该mapper继承BaseMapper就可以使用其中的一些方法

@Repository
public interface UserMapper extends BaseMapper<User> {
}

insert

userMapper.insert(user);

MyBatis-Plus默认的主键策略是:ID_WORKER 全局唯一ID (基于雪花算法的策略生成id)

deleteById

userMapper.deleteById(1511604736883720194L)

deleteBatchIds

List<Long> idList = Arrays.asList(6L, 7L, 9L);

int result = userMapper.deleteBatchIds(idList);

deleteByMap

Map<String, Object> map = new HashMap<>();
map.put("age", 28);
map.put("name", "Test08");
int result = userMapper.deleteByMap(map);

updateById

user.setId(4L);

user.setName("李四");

int result = userMapper.updateById(user);

selectById

User user = userMapper.selectById(1L);

selectBatchIds

List<Long> idList = Arrays.asList(1L,2L,3L);

List<User> list = userMapper.selectBatchIds(idList)

selectByMap

Map<String, Object> map = new HashMap<>();
map.put("age", 28);
map.put("name", "Tom");
List<User> list = userMapper.selectByMap(map);

  Service

官方:持久层接口 | MyBatis-Plus (baomidou.com)

public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

常用注解

 @TableName

mapper通过泛型User匹配数据库的表,支持驼峰,但是如果表名是tb_user,那么就匹配不了了,可以在User类头部加入@TableName(“tb_user”)

这个问题可以通过配置文件解决,在application.properties中配置

#设置Mybatis-Plus操作表的默认前缀
mybatis-plus.global-config.db-config.table-prefix=t_

@TableId

1.在User字段中的某个属性,如uid头上,会把uid作为主键,insert的时候通过雪花算法填充

2.@TableId(value="xxxx")添加在某个属性上,可以用于把该属性映射到表中的XXX字段,并把该字段作为主键

3.@TableId的type属性 

type属性用来定义主键策略

  • IdType.ASSIGN_ID(默认):基于雪花算法的策略生成数据id,与数据库id是否设置自增无关
  • IdType.AUTO:使用数据库的自增策略,要确保数据库设置了id自增, 否则无效

@TableField

Mybatis-plus支持驼峰转换,比如属性为UserName但是数据库中为user_name,他是可以识别的,但是如果属性为username,表中为name,就需要在该属性上加上@TableField("name") 

@TableLogic 

@TableLogic
private Integer isDelete;实现逻辑删除

Wrapper

QueryWrapper

1.查询

构建QueryWrapper对象,构造查询条件,借用mapper的selectList包装查询对象

//查询用户名包含a,年龄在20到30之间,并且邮箱不为null的用户信息

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "a")
        .between("age", 20, 30)
        .isNotNull("email")
        .orderByAsc("age");
List<User> list = userMapper.selectList(queryWrapper);

2.删除

建QueryWrapper对象,构造查询条件,借用mapper的delete删除查询对象

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
int result = userMapper.delete(queryWrapper);//删除email为空的所有记录

3.更新

建QueryWrapper对象,构造查询条件,借用mapper的update更新查询到的对象

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改
//UPDATE t_user SET age=?, email=? WHERE (username LIKE ? AND age > ? OR email IS NULL)
queryWrapper
        .like("name", "a")
        .gt("age", 20)
        .or()
        .isNull("email");
User user = new User();
user.setEmail("user@test.com");
int result = userMapper.update(user, queryWrapper);

4.选择一些列

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "a")
        .between("age", 20, 30)
        .isNotNull("email")
        .orderByAsc("age");
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(user -> System.out.println(user));
queryWrapper.select("name", "age");
//selectMaps()返回Map集合列表,通常配合select()使用,避免User对象中没有被查询到的列值为null
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
maps.forEach(System.out::println);

5.构造子查询

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("id", "select id from user where id <= 3");
List<User> list = userMapper.selectList(queryWrapper);

UpdateWrapper

可以认为还是用UpdateWrapper构造了查询结果,最终还是用的userMapper的update更新

UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
updateWrapper.like("name","a")
        .and(i->i.gt("age",20).or().isNull("email"));
updateWrapper.set("email","user@test08.com");
int result = userMapper.update(null,updateWrapper);

注意:int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);函数的作用是根据给定的updateWrapper条件,更新数据库中与之匹配的记录,将这些记录的数据更新为entity所代表的内容。

condition

对标mybatis的条件查询,如果哪个字段不为空,那么这个字段也要参与select

1.使用if

String username = null;
        Integer ageBegin = 18;
        Integer ageEnd = 20;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//StringUtils.isNotBlank()判断某字符串是否不为空且长度不为0且不由空白符(whitespace)构成
        if(StringUtils.isNotBlank(username)){
            queryWrapper.like("name","a");
        }
        if(ageBegin != null){
            queryWrapper.ge("age", ageBegin);
        }
        if(ageEnd != null){
            queryWrapper.le("age", ageEnd);
        }
//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE (age >=? AND age <= ?)
        List<User> users = userMapper.selectList(queryWrapper);

2.使用带condition参数的重载方法构建查 询条件,简化代码的编写

LambdaQueryWrapper 

相对于QueryWrapper 只修改了对于数据库字段的直写,之前直接写"age",现在通过pojo类映射数据库字段

LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//StringUtils.isNotBlank()判断某字符串是否不为空且长度不为0且不由空白符(whitespace)构成
queryWrapper.like(StringUtils.isNotBlank(username),User::getName,username)
        .ge(ageBegin!=null,User::getAge,ageBegin)
        .le(ageEnd!=null,User::getAge,ageEnd);
//SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE (age >=? AND age <= ?)
List<User> users = userMapper.selectList(queryWrapper);

LambdaUpdateWrapper

插件

分页插件

法一:

这样就可以在service层实现分页查询了

1.添加配置类

@Configuration
@MapperScan("com.hua.mybatisplus.mapper") //可以将主类中的注解移到此处
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

2.调用mapper实现分页查询

Page<User> page = new Page<>(1,3);
userMapper.selectPage(page,null);//这里第二个参数可以传入一个Wrapper帮助实现限制查询
//获取分页数据
List<User> list = page.getRecords();

法二:使用xml自定义分页查询

userMapper.java

Page<User> selectPageVo(
            //page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位
            Page<User> page,
            //age 年龄 限制条件
            Integer age);

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.note.note.mapper.UserMapper">
    <!--    Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);-->
    <!--SQL片段,记录基础字段-->
    <!--    Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);-->
    <!--SQL片段,记录基础字段-->
    <sql id="BaseColumns">id,name,age,email</sql>
    <select id="selectPageVo" resultType="com.note.note.domain.User">
        SELECT <include refid="BaseColumns"></include> FROM user
        WHERE age > #{age}
    </select>
</mapper>

对比一下mybatis+pagehelper

具体来说,当 PageHelper.startPage(categoryPageQueryDTO.getPage(),categoryPageQueryDTO.getPageSize()) 被调用时,PageHelper 会拦截接下来的第一条查询 SQL 语句,并向其中注入相应的 limit 子句来实现分页查询。同时,PageHelper 会利用 ThreadLocal 线程变量来保存分页的信息,以确保只有在该查询执行期间有效。

//service层
public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
        PageHelper.startPage(categoryPageQueryDTO.getPage(),categoryPageQueryDTO.getPageSize());
        //下一条sql进行分页,自动加入limit关键字分页
        Page<Category> page = categoryMapper.pageQuery(categoryPageQueryDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }
//mapper
Page<Category> pageQuery(CategoryPageQueryDTO categoryPageQueryDTO);

//xml
<select id="pageQuery" resultType="com.sky.entity.Category">
        select * from category
        <where>
            <if test="name != null and name != ''">
                and name like concat('%',#{name},'%')
            </if>
            <if test="type != null">
                and type = #{type}
            </if>
        </where>
        order by sort asc , create_time desc
    </select>

 乐观锁

如果a想要对价格+50,b想-30,两个人同时读到价格100,那么最后结果可能是150/70,而不是120,可以通过加上乐观锁版本号,每次修改都++,每次修改前核对版本号,如果版本号和预期相同才修改,CAS

做法就是加上@Version字段,配置拦截器(加上乐观锁)

@Configuration
@MapperScan("com.note.note.mapper") //可以将主类中的注解移到此处
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor my() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

枚举

@Getter
public enum SexEnum {
    MALE(1,"男"),
    FEMALE(2,"女");
 
    @EnumValue //当一个枚举类型需要写入数据库的时候,就把注解标识的属性的值存储到数据库中
    private Integer sex;
    private String sexName;
 
    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }
}

扩展

DB静态工具

//如果需要联合查询,如在user中需要查询这个user的所有address,就需要注入addressMapper,而在address中有时又要查询对应的user信息,就需要在address中注入userMapper,这样形成了循环依赖(springboot解决了这个问题)

//所以引入静态工具

Integer id=1;
List<Address> list = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();

JSON

这样可以把数据库中读到的json类型的数据直接映射为java类

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值