MyBatis-Plus与Springboot整合、分页功能、ActiveRecord

6 篇文章 0 订阅
1 篇文章 0 订阅
本文详细介绍了如何将MyBatis-Plus集成到SpringBoot项目中,包括MyBatis-Plus的基本概念、特性、支持的数据库、架构,以及SpringBoot配置、实体类、Mapper接口的创建和使用。文章还展示了增删改查操作的示例,涉及条件构造器、分页查询和ActiveRecord模式,帮助开发者快速上手MyBatis-Plus。
摘要由CSDN通过智能技术生成

MyBatis-Plus与Springboot整合

MyBatis-Plus官网:http://www.baomidou.com

1. MyBatis-Plus介绍

1.1 MyBatis-Plus简介

简称MP,是MyBatis的增强工具(并不是取代),在MyBatis原有技术之上进行的增强,而不是改变,简化了MyBatis开发步骤,常见的操作封装成了方法。提升了开发效率。

1.2 特性

无侵入:不做改变,引入不会对原有工程产生任何影响。

损耗小:常见的CRUD操作自动注入,直接面向对象。

强大数据操作(CRUD):将常规Mapper操作,进一步进行了封装,直接可以通过调用方法的形式来实现数据库的CRUD。

自动生成主键:支持主键的生成策略。

内嵌代码生成器:采用内置插件,可以快速生成Mapper的映射。

内置分页插件:基于MyBatis物理实现分页。

1.3 支持数据库

支持的关系型种类:

  • MySQL、MariaDB、DB2、Oracle、SQL Server、SQLite…
  • 达梦、虚谷、南大…

1.4 MyBatis-Plus架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UkpaEYWK-1668165984706)(/Users/yuanxin/Documents/课件/SpringBoot-V2.1-20220710/unit03-Spring Boot数据访问/01-Spring Boot数据访问教程/images/8.jpeg)]

2.SpringBoot整合MyBatis-Plus

1 MyBatis-Plus配置

1.引入依赖:MyBatis-Plus依赖。

l<!-- 项目依赖 -->
<dependencies>
  <!-- 引入了单元测试的启动器 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <!-- 1.MySQL数据库驱动 -->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
  </dependency>
  <!-- 连接池 -->
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.17</version>
  </dependency>
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
  </dependency>
</dependencies>

2.创建对应的表语句。

CREATE TABLE t_product (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50), #商品名称
  price DOUBLE,
  flag VARCHAR(2), #上架状态
  goods_desc VARCHAR(100), #商品描述
  images VARCHAR(400), #商品图片
  goods_stock INT, #商品库存
  goods_type VARCHAR(20), #商品类型
  created_user VARCHAR(20) COMMENT '日志-创建人',
	created_time DATETIME COMMENT '日志-创建时间',
	modified_user VARCHAR(20) COMMENT '日志-最后修改执行人',
	modified_time DATETIME COMMENT '日志-最后修改时间'
);

INSERT INTO t_product VALUES (
			NULL,
			'HUAWEI P60', 
			6999, 
			'1', 
			'华为P60 5G手机 分期 麒麟990 晨曦金 8+256GB', 
			'https://img14.360buyimg.com/5f4da578E7c6efde1/2cd53a53083ab2ed.jpg', 
			99, 
			'1',
			'admin', 
			'2022-11-04 15:46:55', 
			'Tom', 
			'2022-11-04 15:46:55');

2.配置properties文件中配置数据库连接相关的信息。

spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=20
spring.datasource.minIdle=10
spring.datasource.maxActive=100

# 开启驼峰命名匹配映射   mybatis-plus内置驼峰映射
#mybatis-plus.configuration.map-underscore-to-camel-case=true
# 输出SQL语句
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 配置MyBatis的XML配置文件位置
mybatis-plus.mapper-locations=classpath:mapper/*.xml
# 配置XML映射文件中指定的实体类别名路径
mybatis-plus.type-aliases-package=com.cy.domain

3.编译一个实体类pojo,映射一张表-Product。

  • @TableName(“表明”):表示当前实体类映射数据库中的那一张表
  • @TableFiled(“表的字段名称”):在表中的字段名称实体类中的属性名称不一致的时候,需要开启映射。
package com.lty.pojo;

import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.omg.CORBA.IDLType;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.io.Serializable;

/**
 * (TProduct)实体类
 *
 * @author makejava
 * @since 2022-11-11 09:54:29
 */
//mybatisplus提供了一个映射的注解@TableName("表明“)
@Component
// @TableName("t_product")
public class Product implements Serializable {
    private static final long serialVersionUID = 348863888757284637L;

    //指定当前实体类中中的属性哪一个与表中的id映射
   //@TableId(type= IdType.AUTO) //支持id自增策略
    private Integer id;
    
    private String name;
    
    private String price;
    
    private String flag;

   // @TableField("goods_desc") //映射关系
    private String goodsDesc;
    
    private String images;
    
    private Integer goodsStock;
    
    private String goodsType;
    /**
     * 日志-创建人
     */
    private String createdUser;
    /**
     * 日志-创建时间
     */
    //@JsonFormat(pattern = "yyyy-MM-dd",timezone = "UTC")
    //插入时填充值 FiledFill.INSERT
    @TableField(fill = FieldFill.INSERT)

    private Date createdTime;
    /**
     * 日志-最后修改执行人
     */
    private String modifiedUser;
    /**
     * 日志-最后修改时间
     */
   // @JsonFormat(pattern = "yyyy-MM-dd",timezone = "UTC")
    @TableField(fill = FieldFill.INSERT_UPDATE)  //插入与更新时自动填充
    private Date modifiedTime;

get/set....

4.配置Druid连接池,并且通过配置类加载指定的连接池(DruidDataSource)。

package com.cy.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource getDruid() {
        return new DruidDataSource();
    }
}

2 Mapper层开发

1.创建Mapper层接口,需要实现一个MyBatis-Plus提供的BaseMapper接口。

BaseMapper: 在该接口中封装数据库的常见操作,增删改查。通过方法的调用直接可以完成简单的数据库操作。

package com.cy.mybaitspluspro.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cy.mybaitspluspro.pojo.Product;
import org.apache.ibatis.annotations.Mapper;

@Mapper // 将当前的接口对应的实现类交给MyBatis工厂来创建
public interface ProductMapper extends BaseMapper<Product> {
    // 不需要编写任何的CRUD操作的方法,天然具有了增删改查的操作
}

2.配置MyBatis-Plus复杂SQL操作的信息。

# 开启驼峰命名匹配映射
#mybatis-plus.configuration.map-underscore-to-camel-case=true
# 输出SQL语句
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 配置MyBatis的XML配置文件位置
mybatis-plus.mapper-locations=classpath:mapper/*.xml
# 配置XML映射文件中指定的实体类别名路径(com.cy.mybatis-plus-demo.pojo.Product)
mybatis-plus.type-aliases-package=com.cy.mybaitspluspro.pojo

3 MyBatis-Plus增删改查

测试包下,创建类MyBatisPlusTests。

1.新增数据数据。insert(T entity)。

2.删除操作:

  • 根据id删除
  • 根据集合中的数据删除
  • 根据指定的条件删除
// 根据id删除数据
@Test
public void test02() {
  int row = productMapper.deleteById(1);
  System.out.println("row=" + row);
}

// 根据ids删除数据
@Test
public void test03() {
  ArrayList<Integer> ids = new ArrayList<>(){{
    add(2);
    add(3);
  }};
  // ids.add(1);
  int row = productMapper.deleteBatchIds(ids);
  System.out.println("row=" + 2);
}

// 根据条件删除数据
@Test
public void test04() {
  // 使用Map接收条件(where的条件)
  // price: 1999
  // name: 小米
  Map<String, Object> col = new HashMap<>(){{
    put("name", "小米");
    put("price", 1999);
  }};
  int row = productMapper.deleteByMap(col);
  System.out.println("row=" + row);
}

@Test
public void test05() {
  /**
         * Wrapper<T> queryWrapper:表示封装的是一个删除条件的对象,读取queryWrapper中的条件,根据设置的条件来删除内容
         *
         * int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
         * 根据entity条件,删除记录
         * 方法:@param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
         */
  // 条件构造器:用来封装删除条件的对象
  UpdateWrapper<Product> wrapper = new UpdateWrapper<>();
  // gt(): 大于,where price > 1000 OR id = 10, name like "%小米%"
  wrapper.gt("price", 2000).or().likeRight("name", "小米");
  productMapper.delete(wrapper);
}

3.修改数据操作。

// 根据商品id更新数据
@Test
public void test06() {
  Product product = new Product();
  product.setId(1); // 根据此id来修改数据库中对应的这条记录
  // 将需要被更新的数据绑定在Product属性上
  product.setName("小米");
  product.setPrice(2999);
  int row = productMapper.updateById(product);
  System.out.println("row=" + row);
}

@Test
public void test07() {
  Product product = new Product();
  product.setId(1); // 更新的是商品id为1的这件商品

  // 需要指定泛型的类型:即表示映射的表对应的实体类
  UpdateWrapper<Product> wrapper = new UpdateWrapper<>();
  // 条件构造器:添加跟新约束的条件
  // update t_product set name="小米旗舰机", price=3999 where goods_stock>10
  // ge(): 表示大于等于
  // name - 小米旗舰机
  // price - 3999
  wrapper.ge("goods_stock", 10).set("name", "小米旗舰机").set("price", 3999).set(false, "goods_stock", null);
  int row = productMapper.update(product, wrapper);
  System.out.println("row=" + row);
}

4.查询数据。

@Test
public void test08() {
  Product product = productMapper.selectById(1);
  System.err.println(product);
}

@Test
public void test09() {
  List<Integer> ids = new ArrayList<>(){{
    add(1);
    add(2);
  }};
  List<Product> products = productMapper.selectBatchIds(ids); // 批量查询数据
  // 输出集合中的所有元素的信息  jdk8的新特性
  products.forEach(System.out::println);
}

@Test
public void test10() {
  // 需求:查询商品的名称是"小米"并且库存大于等于5

  UpdateWrapper<Product> wrapper = new UpdateWrapper<>();
  wrapper.ge("goods_stock", 5).eq("name", "小米");
  // 快捷键:soutc
  productMapper.selectList(wrapper).forEach(System.out::println);
}

5.条件+分页查询。

  • selectPage():表示根据条件进行分页查询。
  • Page: 封装查询页的信息
  • UpdateWrapper:查询的条件构造器
 @Test
    public void test13(){
        //根据条件进行分页查询
        //分页信息  需要传递表的实体类映射
        IPage<Product> page=new Page<>(1,1);

        //件构造器----使用queryWrapper   增删改使用updateWrapper
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.like("name","米");

        IPage<Product> productIPage = productMapper.selectPage(page, wrapper);
        List<Product> list = productIPage.getRecords();
        for (Product product1 : list) {
            System.out.println(product1);
        }
    }

运行后我们会发现,并没有实现分页功能,仍旧输出了满足条件查询下的所有,因此,需要写如下配置

@Configuration
public class PageConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

6.MyBatis-Plus复杂查询

1.TableFiled字段:设置某些字段的默认取值(在某种情况下被触发)。

  • FieldFill.ISERT:只有在插入时才会自动填充字段的取值
  • FieldFill.INSERT_UPDATE: 只有在插入或者跟新的时候字段自动取值
   //插入时填充值 FiledFill.INSERT
    @TableField(fill = FieldFill.INSERT)

    private Date createdTime;
    /**
     * 日志-最后修改执行人
     */
    private String modifiedUser;
    /**
     * 日志-最后修改时间
     */
   // @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    @TableField(fill = FieldFill.INSERT_UPDATE)  //插入与更新时自动填充
    private Date modifiedTime;

2.定义处理器(Handler),配置对象源数据信息(就是默认值的意思)。

  • MetaObjectHandler接口:表示给指定的pojo实体类设置默认的取值(在什么状态下)。
  • 实现接口中的方法即可。
//自定义源数据对象处理器,设置pojo实体类字段的默认值
@Component //非mvc层
public class MetaObject implements MetaObjectHandler {
    //插入时调用
    @Override
    public void insertFill(org.apache.ibatis.reflection.MetaObject metaObject) {
        //自动填充创建事件和修改时间
        /**
         * mybatisPlus3.3.3 版本后可用
         * 参数1:操作的对象
         * 参数2:哪个属性设置默认取值
         * 参数3:目标取值的数据类型.class
         * 参数4:目标属性的默认具体取值
         */
        this.strictInsertFill(metaObject, "createdTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "modifiedTime", Date.class, new Date());
    }

    //跟新时调用
    @Override
    public void updateFill(org.apache.ibatis.reflection.MetaObject metaObject) {
        //修改时调用
        this.strictUpdateFill(metaObject, "modifiedTime", Date.class, new Date());
    }
}

**注意:**数据库插入的时间可能不是当前系统时间

image-20221111180901465

​ 解决办法:可能url的时区有问题,可以改为:

url: jdbc:mysql://localhost/mybatis-plus?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai

3.简化版连接数据库

​ 上面我们导入了druid数据库连接池的jar包,然后配置了type: com.alibaba.druid.pool.DruidDataSource,然后我们配置了数据库的配置类。

简化版:

  • 只导入druid-spring-boot-starter的jar包与·mysql的jar包
  • 无需配置数据库连接池的类型
  • 无需写数据库的配置类
  • 可以直接使用

**原因:**druid的启动器里面已经包含了druid的jar包,sprigboot会自动识别配置

4. 使用MybatisPlus的高级配置

# 开启驼峰命名匹配映射
#mybatis-plus.configuration.map-underscore-to-camel-case=true
# 输出SQL语句
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 配置MyBatis的XML配置文件位置
mybatis-plus.mapper-locations=classpath:mapper/*.xml
# 配置XML映射文件中指定的实体类别名路径
mybatis-plus.type-aliases-package=com.lty.domain
# 配置全局表的前缀   可以省略@TableName
mybatis-plus.global-config.db-config.table-prefix=t_  
#配置全局id自增  可以省略@TableId(Type = IdType.AUTO)
mybatis-plus.global-config.db-config.id-type=auto

5. 条件构造器(基本操作):

1. 比较

  • eq:等于
  • ne:不等于
  • gt:大于
  • ge:大于等于
  • lt:小于
  • le:小于等于
  • between
  • notBetween
  • in:字段 IN (value.get(0), value.get(1), …)
  • notIn:字段 NOT IN (v0, v1, …)

2. 模糊查询

  • like:LIKE ‘%值%’
  • likeLeft : LIKE ‘%值’
  • likeRight:LIKE ‘值%’

3. 排序

  • orderBy 默认升序
  • OrderByAsc:ORDER BY 字段, … ASC 升序
  • prderByDesc:排序:ORDER BY 字段, … DESC

4. 逻辑查询

  • or:主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用 or 则默认为使用 and 连接)
  • and:例: and(i -> i.eq(“name”, “李白”).ne(“status”, “活着”)) —> and (name = ‘李白’ and status
    <> ‘活着’)

6. ActiveRecord

什么是ActiveRecord?
ActiveRecord也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记
录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而
且简洁易懂。
ActiveRecord的主要思想是:
每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;
通常表的每个字段在类中都有相应的Field;
ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;;
ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑;

1. 开启AR

在MP中,开启AR非常简单,只需要将实体对象继承Model即可。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends Model<User> {
	private Long id;
	private String userName;
	private String password;
	private String name;
	private Integer age;
	private String email;
}

2.根据主键查询

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testAR() {
User user = new User();
user.setId(2L);
User user2 = user.selectById();
System.out.println(user2);
}
}

3. 新增数据

RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testAR() {
User user = new User();
user.setName("刘备");
user.setAge(30);
user.setPassword("123456");
user.setUserName("liubei");
user.setEmail("liubei@itcast.cn");
boolean insert = user.insert();
System.out.println(insert);

在这里插入图片描述

4.更新操作

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
	@Autowired
	private UserMapper userMapper;
	@Test
	public void testAR() {
		User user = new User();
		user.setId(8L);
		user.setAge(35);
		boolean update = user.updateById();
		System.out.println(update);
	}
}

在这里插入图片描述

5. 删除

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
	@Autowired
	private UserMapper userMapper;
	@Test
	public void testAR() {
		User user = new User();
		user.setId(7L);
		boolean delete = user.deleteById();
		System.out.println(delete);
	}
}

结果:

[main] [cn.itcast.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: DELETE FROM
tb_user WHERE id=?
[main] [cn.itcast.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Parameters: 7(Long)
[main] [cn.itcast.mp.mapper.UserMapper.deleteById]-[DEBUG] <== Updates: 1

6. 根据条件查询

RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
	@Autowired
	private UserMapper userMapper;
	@Test
	public void testAR() {
		User user = new User();
		QueryWrapper<User> userQueryWrapper = new 												QueryWrapper<>();
 		userQueryWrapper.le("age","20");
		List<User> users = user.selectList(userQueryWrapper);
		for (User user1 : users) {
		System.out.println(user1);
		}
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值