Mybatis-plus

一、快速入门

1,导入依赖

  • 导入mybatis需要的依赖

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.1</version>
    </dependency>

2,配置文件

  • 配置数据库连接池

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mpdb?  useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF8&useUnicode=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource

3,创建表

CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `password` varchar(32) NOT NULL,
  `age` int NOT NULL,
  `tel` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1655401039546839042 DEFAULT CHARSET=utf8mb3;

4,创建实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
​
     private Long id;
     private String name;
     private String password;
     private Integer age;
     private String tel;
}

5,继承类

  • mapper层继承类BaseMapper

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

6,测试

/**
 * @author 星辰鱼
 * @version 1.0
 * @date 2023/5/8 10:03
 */
@SpringBootTest
class UserMapperTest {
​
    @Autowired
    private UserMapper userMapper;
​
    /**
     * 查询
     */
    @Test
    public void selectListTest(){
        // 查询所有
        List<User> userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
    }
​
}

二、简单的CRUD

1,删除

/**
 * 删除
 */
@Test
public void delete(){
    // 根据id删除一个
    int i = userMapper.deleteById(5);
    System.out.println(i);
​
    int i1 = userMapper.deleteBatchIds(Arrays.asList(6, 7, 8));
    System.out.println(i1);
}

2,修改

/**
 * 修改
 */
@Test
public void update(){
    User user = User.builder()
            .id(1L)
            .name("汤姆")
            .password("111111")
            .age(888)
            .tel("16798761234")
            .build();
    int i = userMapper.updateById(user);
    System.out.println(i);
}

3,增加

/**
 * 增加
 */
@Test
public void insert(){
    User user = User.builder()
            .name("关云长")
            .password("123456")
            .age(35)
            .build();
    int insert = userMapper.insert(user);
    System.out.println(insert);
}

4,查询

/**
 * 查询
 */
@Test
public void selectListTest(){
    // 查询所有
    List<User> userList = userMapper.selectList(null);
    userList.forEach(System.out::println);
​
    // 根据id查询
    User user = userMapper.selectById(6);
    System.out.println(user);
​
    // 根据多个id查询
    List<User> users = userMapper.selectBatchIds(Arrays.asList(5, 6, 7, 8));
    users.forEach(System.out::println);
}

三、分页查询

1,创建拦截器

1,PaginationInnerInterceptor()

PaginationInnerInterceptor不是spring容器的组件,只能使用new方法

@Configuration
public class MpConfig {
​
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
​
        // mybatis-plus 的拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
​
        // 添加分页拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        
        return interceptor;
    }
​
}

2,测试

@Test
public void pageTest(){
    
    // 分页构造函数(当前页码,每页显示条数)
    // pages包含查询的结果
    IPage<User> pages = new Page<>(2, 3);
    
    // 添加分页条件
    userMapper.selectPage(pages, null);
    
    // 分页记录列表
    List<User> records = pages.getRecords();
    System.out.println("records = " + records);
    
    // 总行数
    long total = pages.getTotal();
    System.out.println("total = " + total);
}

四、yml文件简单配置

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启日志
    map-underscore-to-camel-case: true # 开启驼峰映射
  type-aliases-package: com.itheima.mp.pojo # 配置别名
  mapper-locations: classpath*:/mapper/**/*.xml

五、DQL(数据查询语言)

1,条件查询

核心接口:

  • QueryWrapper:根据数据库字段名查询

  • LambdaQueryWrapper:使用Lambda表达式查询

  • LambdaUpdateWrapper:使用Lambda表达式更新

执行条件判断:

  • lt:less than 小于

  • le:less than or equal to 小于等于

  • eq:equal to 等于

  • ne:not equal to 不等于

  • ge:greater than or equal to 大于等于

  • gt:greater than 大于

  • 多条件关系 and ,or

  • 是否拼接过滤条件的判断

/**
 * DQL(数据查询语言)
 */
@Test
public void queryWrapperTest(){
​
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
​
    // SELECT id,name,password,age,tel FROM user WHERE (name = '汤姆')
    queryWrapper.eq("name", "汤姆");
​
    // (age > 15) - 相当于在上面的sql变成了
    // gt > , ge >= , lt < , le <=
    // SELECT id,name,password,age,tel FROM user WHERE (name = '汤姆' AND age > 15)
    queryWrapper.gt("age", 15);
​
    // 当多条件关系为or时
    // 相当于拼接了 (OR name LIKE '%j%')
    queryWrapper.or().like("tel", "456");
​
    // 【pwd != null】为true时才会拼接后面的条件(OR password = '111111')
    String pwd = "111111";
    queryWrapper.or().eq(pwd != null, "password", pwd);
​
    /**
     * 最终语句
     * SELECT
     *     id, `name`, `password`, age, tel
     * FROM `user`
     * WHERE (
     *     `name` = '汤姆' AND age > 15
     *     OR tel LIKE '%456%' OR PASSWORD = '111111'
     * )
     */
    List<User> users = userMapper.selectList(queryWrapper);
}

2,投影查询

返回部分列的数据,而不是所有列的数据,可以用投影查询。

让结果集包含指定列

  • 例如:SELECT 列1, 列2, 列3 FROM ...;

LambdaQueryWrapper 比 QueryWrapper 更方便,其他二者每页区别。

    /**
     * 投影查询
     */
    @Test
    public void projection(){
​
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        
        // SELECT `name` FROM `user` 
        queryWrapper.select(User::getName)
                // GROUP BY `name` 
                .groupBy(User::getName)
                // ORDER BY `name` DESC
                .orderByDesc(User::getName);
        
        // 最终结果: SELECT `name` FROM `user` GROUP BY `name` ORDER BY `name` DESC
        List<User> users = userMapper.selectList(queryWrapper);
    }
//【 错误写法1: 打印的sql中or拼接没有加括号:SELECT COUNT( * ) FROM pm_project WHERE `del_flag` = 0 AND
// ( id = 287 AND `project_status` = '1' OR `project_status` = '2' OR `project_status` = '3' OR `project_status` = '4' AND `del_flag` = '0' );
//          LambdaQueryWrapper<PmProject> lqw = Wrappers.lambdaQuery();
//          lqw.eq(PmProject::getId,id)
//             .eq(PmProject::getProjectStatus, '1').or()
//             .eq(PmProject::getProjectStatus, '2').or()
//             .eq(PmProject::getProjectStatus, '3').or()
//             .eq(PmProject::getProjectStatus, '4')
//             .eq(PmProject::getDelFlag, '0');

3,ORM映射

在数据库设计不合理时使用,即数据库表名与字段名与类的类名与属性名不遵循驼峰映射时使用。

建议合理设计数据库。

3.1,映射表名

@TableName("tb_user")

在数据库表对应的实体类上注解,表示对应的数据库表的名称

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("tb_user")
public class User {
    // ......
}

3.2,映射属性名

@TableField("username")

在数据库表对应的实体类上注解,表示对应的数据库表的字段的名称

@TableField("username")
private String name;

3.3 其他

@TableField(select = false)
private String tel;

表示查询时不查询这个属性对应的字段

@TableField(exist = false)
private List<String> str;

表示该属性在对应的数据库中没有对应的字段

3.4,举例

/**
 * @author 星辰鱼
 * @version 1.0
 * @date 2023/5/8 10:01
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("tb_user")
public class User {
​
     private Long id;
     @TableField("username")
     private String name;
     private String password;
     private Integer age;
​
     /**
      * 表示该字段不参与查询
      * SELECT id,username AS name,password,age FROM tb_user WHERE id IN ( ? , ? , ? , ? )
      */
     @TableField(select = false)
     private String tel;
​
     /**
      * 表示该属性在对应的数据库中没有对应的字段
      */
     @TableField(exist = false)
     private List<String> str;
}

六、DML(数据操纵语言)

1,主键生成策略与主键回填

局部配置:

/**
* IdType.ASSIGN_ID : 表示插入数据时,ID自增
* ASSIGN_ID :表示雪花算法生成ID
* ASSIGN_UUID(4) : 表示UUID生成ID
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;

全局配置:

mybatis-plus:
# mybatis-plus 全局配置
global-config:
db-config:
 id-type: auto # 配置主键自增
 table-prefix: tb_

局部配置优先于全局配置

  • 主键会自动回填

2,逻辑删除

一般而言,不建议直接将数据库的字段删除。

所有通常会定义一个逻辑删除字段,通过这个字段的值来判断该数据的状态。

1,在数据库添加逻辑删除字段

2,在实体类使用注解标记表示逻辑删除的属性

/**
* 逻辑删除字段
*/
@TableLogic
private Integer deleted;

3,全局配置

mybatis-plus:
global-config:
db-config:
 logic-delete-field: deleted # 表示逻辑删除的成员变量
 logic-delete-value: 1 # deleted = 1,表示删除
 logic-not-delete-value: 0 # deleted = 1,表示不删除

配置后,删除会将数据库的deleted值变为1

UPDATE tb_user SET deleted=1 WHERE id=? AND deleted=0

查询语句也会变化

SELECT id,username AS name,password,age,create_time,deleted FROM tb_user WHERE deleted=0

3,乐观锁

乐观锁有一个关于版本号的字段【version】

修改数据前会先查询当前的【version】字段的值,然后设置对应的条件修改。

修改数据的同时,也会将【version】的值加1

UPDATE tb_user SET username=?, password=?, age=?, version=version + 1
WHERE id=? AND version=?

举例说明:

甲乙同时修改一个数据,他们会先获取改数据的version值,然后开始修改。
假设甲先修改,先判断version值,修改后将version值加1。
乙修改时,原本获取的version值与现在的version值不匹配,结果就无法修改。

3.1,实现步骤

1,添加数据库字段

2,增加实体类对应的字段

@Version
private Integer version;

3,配置乐观锁拦截器

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
​
    // mybatis-plus 的所有拦截器
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
​
    // 乐观锁拦截器
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
​
    return interceptor;
}

4,测试

/**
 * 模拟乐观锁
 */
@Test
public void locker(){
    Long id = 1655493503825780737L;
    // 1,一先查
    User user1 = userMapper.selectById(id);
    // 2,二后查
    User user2 = userMapper.selectById(id);
    // 3,二先改
    user2.setPassword("1234");
    userMapper.updateById(user2);
    // 4,一后改
    user1.setPassword("4321");
    
    userMapper.updateById(user1);
}

最终二改成功,一改失败

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值