Mybatis - Plus 框架

今天无脑将介绍 Mybatis - Plus + Spring Boot 框架的基本使用,开启低代码时代,分享给大家,希望帮助大家大幅提高开发能力!

一、Mybatis - Plus 介绍

1.1 概述

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

MyBatis-Plus 提供了强大的条件构造器(Wrapper)来构建查询条件,包括 QueryWrapper 和UpdateWrapper 等。

1.2 特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、Mybatis - Plus 框架使用

2.1 导入依赖

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <!-- Mybatis - Plus 依赖 -->
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.2</version>
  </dependency>

  <dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
  </dependency>

  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>RELEASE</version>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

2.2 mapper 层和 service 层

/**
 * <p>
 * 存储用户信息的表 服务实现类
 * </p>
 *
 * @author qf
 * @since 2023-11-02
 */
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {

}

/**
 * <p>
 * 存储用户信息的表 Mapper 接口
 * </p>
 *
 * @author qf
 * @since 2023-11-02
 */
@Mapper
public interface UsersMapper extends BaseMapper<Users> {

}

2.3 使用内置方法执行 SQL 语句

  • QueryWrapper<Users>.lambda():表示是使用 Lambda 表达式的方法进行操作。

2.3.1 查询

  • select(String... columns):指定查询的字段,可以选择需要查询的字段。
  • selectOne:用于查询满足条件的单个实体记录。
  • selectList:用于查询数据库并返回一个列表。
  • Integer selectCount(Wrapper<T> queryWrapper):根据条件查询记录数量
  • T selectById(Serializable id):根据主键查询一条记录
  • List<T> selectBatchIds(Collection<? extends Serializable> idList):根据主键批量查询记录
  • List<T> selectByMap(Map<String, Object> columnMap):根据条件查询记录

2.3.1.1 无条件和有条件查询
// 查询单个用户数据
QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(Users::getId,9999);
Users users = usersMapper.selectOne(queryWrapper);

// 查询 id 为 9999 的用户数据
QueryWrapper<Users> qw = new QueryWrapper<>();
qw.lambda().eq(Users::getId,9999);
List<Users> users = usersMapper.selectList(qw);

// 查询 id 大于 9999 的用户数据
QueryWrapper<Users> qw = new QueryWrapper<>();
qw.lambda().gt(Users::getId,9999);
List<Users> users = usersMapper.selectList(qw);

// 查询 id 小于等于 9999 的用户数据
qw.lambda().le(Users::getId,9999);

// 查询 id 在 [3000026, 3000030] 的数据,包头包尾
qw.lambda().between(Users::getId,3000026, 3000030);

// 查询 id 包含 6 的用户数据
qw.lambda().like(Users::getId,6);
// 查询 id 不包含 6 的用户数据
qw.lambda().notLike(Users::getId,6);

// 查询 id 等于 3000026,并且 密码为 123456 的用户数据
qw.lambda()
        .and(i -> i.eq(Users::getId, 3000026))
        .and(i -> i.eq(Users::getPassword, 123456));

// 下面都查询 id 等于 3000027,或 密码为 123456 的用户数据
qw.lambda()
        .and(i -> i.eq(Users::getId, 3000027))
        .or(i -> i.eq(Users::getPassword, 123456));
qw.lambda()
        .or(i -> i.eq(Users::getId, 3000027))
        .or(i -> i.eq(Users::getPassword, 123456));

// 下面都查询 id 不等于 3000027,或 密码不是 123456 的用户数据
qw.lambda()
        .not(i -> i.eq(Users::getId, 3000027))
        .not(i -> i.eq(Users::getPassword, 123456));

// 按照 id 进行降序排序查询数据
qw.lambda().orderByDesc(Users::getId);
List<Users> users = usersMapper.selectList(qw);

// 查询 u_id 、u_password 用户数据
qw.lambda().select(Users::getId, Users::getPassword);
List<Users> users = usersMapper.selectList(qw);

// 查询 id 在 小于 3000028 的语句里的数据,如 in (...,3000028)
qw.inSql("u_id",  "select u_id from users where u_id < 3000028");
List<Users> users = usersMapper.selectList(qw);

2.3.1.2 分页查询
  • 查询会有问题,打印的是全部数据。
 /* Page<Users> page = new Page<>(1,2);
        QueryWrapper<Users> qw = new QueryWrapper<>();
        qw.lambda().ne(Users::getId,9999);
        IPage<Users> userPage = usersMapper.selectPage(page, qw);
        List<Users> users = userPage.getRecords();
        System.out.println(users);*/
        IPage<Users> page = Page.of(1, 2);
        QueryWrapper<Users> qw = new QueryWrapper<>();
        qw.lambda().ge(Users::getId,99990);
        List<Users> list = iUsersService.list(page, qw);
        System.out.println(list);
2.3.1.3 分组查询
  • 无 having 条件
// 查询 role_id 对应的数量总和
qw.select("role_id","count(role_id) as c").groupBy("role_id");
List<Map<String, Object>> users = usersMapper.selectMaps(qw);

// 打印结果:
// [{c=3, role_id=1}, {c=92, role_id=2}, {c=5, role_id=3}, {c=8, role_id=4}, ......]

  • 有 having 条件
// 查询数量大于等于 5 且 小于等于 7 的数据
qw.select("role_id","count(role_id) as c")
	.groupBy("role_id").having("c >= {0} and c <= {1}",5,7);
List<Map<String, Object>> users = usersMapper.selectMaps(qw);
// 打印结果:
// [{c=5, role_id=3}, {c=6, role_id=5}, {c=7, role_id=6}]

// 查询数量 在 (5,7,6) 里的数据
qw.select("role_id","count(role_id) as c").groupBy("role_id").having("c in (5,7,6)");
List<Map<String, Object>> users = usersMapper.selectMaps(qw);
// 打印结果:
// [{c=5, role_id=3}, {c=6, role_id=5}, {c=7, role_id=6}]
2.3.1.4 自定义查询条件
  • apply(String applySql, Object... params):自定义 SQL 条件
qw.apply("u_id >= {0} and u_password = {1} ",  9999, "123456");
List<Users> users = usersMapper.selectList(qw);
2.3.1.5 批量查询
  • List<T> selectBatchIds(Collection<? extends Serializable> idList):根据主键批量查询记录。
// 批量查询 id 为 9999,3000026,3000027 的用户数据
List<Integer> list = new ArrayList<>();
Collections.addAll(list,9999,3000026,3000027);
List<Users> users = usersMapper.selectBatchIds(list);

2.3.2 增加

  • int insert(T entity):插入一条记录。
  • int insertBatchSomeColumn(List<T> entityList):批量插入记录。
  • int insertOrUpdate(T entity):插入或更新一条记录。
  • int insertOrUpdateBatchSomeColumn(List<T> entityList):批量插入或更新记录。

 // 插入一条用户记录
Users users = new Users();
users.setId(1000);
users.setPassword("123");
users.setImgUrl(null);
users.setIsActive(true);
users.setIsDeleted(true);
users.setRoleId(1);
int count = usersMapper.insert(users);

2.3.3 更新

  • int updateById(T entity):根据主键更新一条记录
  • int update(T entity, Wrapper<T> updateWrapper):根据条件更新记录
  • int updateBatchById(List<T> entityList):批量更新记录

// 根据 id 为 1000 进行修改用户数据
Users users = new Users();
users.setId(1000);
users.setPassword("12356");
users.setImgUrl(null);
users.setIsActive(true);
users.setIsDeleted(true);
users.setRoleId(1);
UpdateWrapper<Users> uw = new UpdateWrapper<>();
uw.lambda().eq(Users::getId, 1000);
int count = usersMapper.update(users, uw);

2.3.4 删除

  • int deleteById(Serializable id):根据主键删除一条记录。
  • int deleteById(T entity):根据对象删除一条记录。
  • int deleteByMap(Map<String, Object> columnMap):根据条件删除记录
  • int delete(Wrapper<T> queryWrapper):根据条件删除记录。
  • int deleteBatchIds(@Param("coll") Collection<?> idList):批量删除。

// 根据用户对象的主键进行删除
Users users = new Users();
users.setId(1000);
users.setPassword("12356");
users.setImgUrl(null);
users.setIsActive(true);
users.setIsDeleted(true);
users.setRoleId(1);
int count = usersMapper.deleteById(users);

三、自定义 SQL

@Select、@Update、@Insert、@Delete 注解或者 XML 映射文件来定义自定义 SQL 查询。

  • 注意:不符合驼峰命名法的还是要自己手写字段映射。

3.1 案例

// 查询 id 小于特定值的用户数据
@Select("Select * from users where u_id < #{id};")
@ResultMap("userResultMap")
List<Users> selectByUserId(@Param("id") Integer id);

<mapper namespace="com.qf.zzp.mybatis_plus.mapper.UsersMapper">
    <resultMap id="userResultMap" type="com.qf.zzp.mybatis_plus.entity.Users">
        <id column="u_id" property="id"/>
        <result column="u_password" property="password"/>
    </resultMap>
</mapper>

实体类:

/**
 * 用户
 * <p>
 * 存储用户信息的表
 * </p>
 *
 * @author qf
 * @time 2023/11/03
 * @since 2023-11-02
 * @see java.io.Serializable
 * @see java.lang.RuntimePermission
 */
@TableName(value = "users")
@Data
public class Users implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 用户ID
     */
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 密码
     */
    @TableField(value = "u_password")
    private String password;

    /**
     * 图片路径
     */
    private String imgUrl;

    /**
     * 激活状态 (1=激活, 0=未激活)
     */
    private Boolean isActive;

    /**
     * 角色 ID
     */
    private Integer roleId;

    /**
     * 删除状态 (1=未删除, 0=已删除)
     */
    private Boolean isDeleted;

}

四、多表查询

多表关联:Mybatis - Plus 还未实现

  • join(String sql):进行多表关联查询。
queryWrapper.join("JOIN dept d ON d.id = user.dept_id");

五、内置方法说明

  • eq() :是一种条件构造器方法,通常用于构建查询条件,用于查询时筛选数据库表中某一列等于指定值的记录。
  • gt() :通常用于创建查询条件,以检索大于某个特定值的数据记录。
  • ge():大于等于条件查询。
  • ne():不等于条件查询。
  • lt():小于条件查询。
  • le():小于等于条件查询。
  • between("column_name", minValue, maxValue):区间条件查询。
  • notBetween("column_name", minValue, maxValue):反向区间条件查询。
  • like():模糊查询。
  • notLike():反向模糊查询。
  • in("column_name", value1, value2, value3):IN 条件查询。
  • and() :用于在查询条件中添加一个 "AND" 条件,将多个条件组合为一个条件,所有条件必须同时满足。
  • or() :用于在查询条件中添加一个 "OR" 条件,允许满足其中任何一个条件即可。
  • not() :用于对条件进行取反操作,即排除满足条件的记录。
  • orderByAsc(String... columns):升序排序。
  • orderByDesc(String... columns):降序排序。
  • groupBy(String... columns):指定 GROUP BY 子句中的字段。
    • having(String sqlHaving, Object... params):指定 HAVING 子句中的条件。
  • inSql(String column, String inValue):使用子查询作为 IN 条件。
  • apply(String applySql, Object... params):自定义 SQL 条件

空值条件

  • isNull(String column):字段为 null 条件
  • isNotNull(String column):字段不为 null 条件
queryWrapper.isNull("address");
queryWrapper.isNotNull("phone");

嵌套条件

    • nested(Consumer<QueryWrapper<T>> consumer):嵌套的查询条件,可以使用 and 和 or 连接多个条件。
queryWrapper.nested(qw -> qw.eq("age", 25).or().like("name", "John"));

Lock 超时条件

    • last(String lastSql):添加在 SQL 的最后,可用于添加 FOR UPDATE 等锁定条件。
queryWrapper.last("FOR UPDATE");

六、PageHelper 分页插件的使用

6.1 PageHelper功能介绍

PageHelper是一个用于MyBatis的分页插件,它提供了丰富的功能来简化和增强数据库分页查询的操作。以下是PageHelper插件的一些主要功能:

  1. 数据库分页查询:PageHelper允许您在数据库查询中轻松实现分页功能,而无需手动编写复杂的SQL语句。您可以指定要查询的页码和每页显示的记录数,并PageHelper将自动为您生成合适的SQL语句。
  2. 总记录数的查询:PageHelper支持自动执行总记录数查询,以获取匹配查询条件的总记录数。这对于生成分页信息和显示分页导航非常有用。
  3. 合理化参数:PageHelper可以自动合理化(normalize)pageNum和pageSize参数,确保它们在合理的范围内。例如,它可以确保页码不小于1,页大小不小于1。
  4. 支持多种数据库:PageHelper支持多种数据库,包括MySQL、Oracle、PostgreSQL、SQL Server等,因此您可以在不同数据库中使用相同的分页查询方式。
  5. 自定义排序:您可以根据需要指定自定义的排序规则,以按照不同字段或多个字段进行排序。
  6. 内置支持Count SQL优化:PageHelper内置了对Count SQL查询的优化,可以提高查询性能。
  7. 支持多层嵌套查询:PageHelper可以处理多层嵌套查询,使得复杂的分页查询也能轻松实现。
  8. 分页信息封装:PageHelper返回的分页结果是一个Page对象,它包含了查询结果数据以及分页信息,如当前页码、总记录数、总页数等。
  9. 可自定义的配置:PageHelper允许您根据项目需求进行灵活的配置,包括设置合理化参数、是否启用总记录数查询、是否启用Count SQL优化等。

6.2 导入依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
</dependency>
<!-- 
下面这个依赖适用于原始的 Mybatis 框架使用
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.3.2</version>
</dependency>-->

6.3 配置文件

6.3.1 配置选项

  1. offsetAsPageNum:
    • 默认值:false
    • 含义:如果设置为true,PageHelper会把参数中的页码值当做偏移量(即起始行号),这意味着页码从1开始,而不是从0开始。例如,页码1对应的偏移量是0,页码2对应的偏移量是1,以此类推。如果设置为false,页码和偏移量一样,从0开始。
  1. rowBoundsWithCount:
    • 默认值:false
    • 含义:如果设置为true,PageHelper会进行count查询,以获取总记录数。这通常用于在分页结果中显示总记录数。启用此选项会在查询分页数据的同时执行额外的count查询,以获取总记录数。如果设置为false,PageHelper不会执行count查询。
  1. reasonable:
    • 默认值:false
    • 含义:如果设置为true,PageHelper会合理化(normalize)pageNum和pageSize参数,确保它们在合理的范围内。合理化会确保页码不小于1,页大小不小于1。如果pageNum小于1,将自动设置为1;如果pageSize小于1,将自动设置为1。如果设置为false,PageHelper不会对pageNum和pageSize进行合理化处理。
  1. pageSizeZero:
    • 默认值:false
    • 含义:如果设置为true,当pageSize为0时,会返回所有的数据,而不是抛出异常。这对于不需要分页的查询可能是有用的。
  1. supportMethodsArguments:
    • 默认值:false
    • 含义:如果设置为true,PageHelper将支持将pageNum和pageSize作为参数传递给MyBatis的查询方法,而不仅仅依赖ThreadLocal中的参数。这可以在使用MyBatis的方法参数时更加灵活。
  1. returnPageInfo:
    • 默认值:none
    • 含义:这个选项决定了PageHelper返回的结果对象类型。默认情况下,返回的是Page对象。可以设置为always,使PageHelper始终返回Page对象,无论是否执行了分页查询。也可以设置为check,以检查是否执行了分页查询,如果没有,返回的是原始的查询结果对象。
  1. params:
    • 默认值:none
    • 含义:此选项用于设置额外的参数,可以按照具体需求进行配置。例如,可以使用params="pageNum=pageNumKey;pageSize=pageSizeKey"将PageHelper的参数名映射到自定义参数名。
  1. countColumn:
    • 默认值:* (所有列)
    • 含义:此选项用于设置用于count查询的列名,通常是数据库表中的主键列名。如果不设置,PageHelper会尝试使用 *(所有列)进行count查询。

PaginationInnerInterceptor 的主要作用是拦截 MyBatis SQL 查询,自动添加分页相关的 SQL 语句,如 LIMIT 或 OFFSET 子句,以实现分页查询的功能。具体作用如下:

  1. 自动分页:PaginationInnerInterceptor 可以拦截 MyBatis 执行的查询语句,自动在查询语句中添加分页参数,以实现分页查询功能。这样,您不需要手动编写分页查询的 SQL 语句。
  2. 分页参数处理:该拦截器可以从查询方法的参数中获取分页参数,包括页码和每页记录数,然后根据这些参数自动生成相应的 SQL 语句。
  3. 排序处理:除了分页,PaginationInnerInterceptor 还可以处理排序参数,根据排序参数自动生成 SQL 中的 ORDER BY 子句。
  4. 自动统计总记录数:该拦截器还能够自动执行一个总记录数查询,以获取匹配查询条件的总记录数,这对于构建分页信息非常有用。

6.3.2 配置代码

/**
 * @author 无戏
 * @projectName
 * @date 2023/11/4 9:10
 */
@Configurable
@MapperScan("com.qf.zzp.mybatis_plus.mapper")
public class PageHelperConfig {

    @Bean
    public PageHelper pageHelper(){
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("offsetAsPageNum", "true");
        properties.setProperty("rowBoundsWithCount", "true");
        properties.setProperty("reasonable", "true");
        pageHelper.setProperties(properties);
        return pageHelper;
    }

    @Bean
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        return new PaginationInnerInterceptor();
    }
}

6.4 获得分页信息

// 开启分页器,第一个参数为当前页吗,第二个参数为每页展示的数据量
PageHelper.startPage(1, 3);
// mybatis-plus 自带查询所有方法
List<Users> users = usersMapper.selectList(null);
// 获得分页信息
PageInfo<Users> pageInfo = new PageInfo<>(users);
long totalRecords = pageInfo.getTotal(); // 获取总记录数
int totalPages = pageInfo.getPages(); // 获取总页数
int currentPage = pageInfo.getPageNum(); // 获取当前页码
int pageSize = pageInfo.getPageSize(); // 获取每页记录数
List<Users> list = pageInfo.getList();
System.out.println("获取总记录数:" + totalRecords);
System.out.println("获取总页数:" + totalPages);
System.out.println("获取当前页码:" + currentPage);
System.out.println("获取每页记录数:" + pageSize);
System.out.println(":" + list);
System.out.println("检查是否有下一页:" + pageInfo.isHasNextPage());
System.out.println("检查是否有上一页:" + pageInfo.isHasPreviousPage());
System.out.println("检查是否为第一页:" + pageInfo.isIsFirstPage());
System.out.println("检查是否为最后一页:" + pageInfo.isIsLastPage());
System.out.println("获取导航页码中的最后一页:" + pageInfo.getNavigateFirstPage());

6.5 特殊符号处理

6.5.1 SQL注入:

为了防止 SQL 注入攻击,我们需要对特殊字符进行转义或者使用参数绑定。在使用 MyBatis 进行数据库查询时,应该尽量使用参数绑定,而不是直接拼接 SQL 语句。参数绑定可以通过使用 #{} 或 ${} 来实现。其中,#{}会将参数值转义后作为预编译参数传递给数据库,而${}则会直接将参数值拼接到 SQL 语句中,所以在使用 ${} 时需要特别注意防止 SQL 注入。

6.5.2 XML 转义:

在 MyBatis 的 XML 配置文件中,如果我们需要在SQL语句中使用特殊字符(如 <、>、& 等),需要进行XML转义,以避免解析错误。常见的转义字符如下:

特殊字符

转义字符

<

<

>

>

&

&

"

"

'

<=

<=

>=

>=

6.5.3 使用 CDATA 区段

<![CDATA[ ]]> 是 xml 语法,在 <![CDATA[ ]]> 内部的所有内容都会被解析器忽略,不进行转义。CDATA 区段可以用来包含一些特殊字符或标记,而不会被XML解析器解析。

特殊字符

编码

<

<![CDATA[<]]>

>

<![CDATA[>]]>

&

<![CDATA[&]]>

"

<![CDATA["]]>

<![CDATA[']]>

<=

<![CDATA[<=]]>

>=

<![CDATA[>=]]>

!=

<![CDATA[!=]]>

七、多数据源

  1. 使用 @DS 切换数据源。

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解。

注解

结果

没有@DS

默认数据源

@DS("dsName")

dsName可以为组名也可以为具体某个库的名称

7.1 导入依赖

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.2</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- pageHelper 分页插件依赖 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.6</version>
        </dependency>
<!--        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.2</version>
        </dependency>-->

        <!-- 多数据源依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
            <version>RELEASE</version>
        </dependency>
    </dependencies>

7.2 配置数据源

7.2.1 properties 文件配置

  • 比较多
spring.datasource.dynamic.primary=master
spring.datasource.dynamic.strict=false
spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/xmbg?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
spring.datasource.dynamic.datasource.master.username=root
spring.datasource.dynamic.datasource.master.password=1234
spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.dynamic.datasource.slave_1.url=jdbc:mysql://localhost:3306/xmbg?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
spring.datasource.dynamic.datasource.slave_1.username=root
spring.datasource.dynamic.datasource.slave_1.password=1234
spring.datasource.dynamic.datasource.slave_1.driver-class-name=com.mysql.cj.jdbc.Driver

7.2.2 yaml 文件配置

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/xmbg?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
          username: root
          password: 1234
          driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://localhost:3306/xmbg?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
          username: root
          password: 1234
          driver-class-name: com.mysql.cj.jdbc.Driver

7.2.3 业务层使用

  • 加 @DS 注解,在方法或类上都可以。在方法上的优先级高于类上的。
/**
 * <p>
 * 存储用户信息的表 服务实现类
 * </p>
 *
 * @author qf
 * @since 2023-11-02
 */
@Service
@DS("slave_1")
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {
    @Autowired
    private UsersMapper usersMapper;
    @Override
    public List<Users> selectByUserId(Integer id) {
        return usersMapper.selectByUserId(id);
    }
}

八、注解说明

@Table: 注解用于指定实体类与数据库表之间的映射关系。主要注解参数如下:

  • value:该属性用于指定数据库表的表名。这是 @TableName 注解中的主要属性,它表示实体类要与哪个数据库表进行映射。
  • resultMap:指定结果映射的 ID。这个参数允许你在 XML 映射文件中指定要使用的结果映射 ID。
  • excludeProperty:排除不需要映射的字段。该参数接受一个字符串数组,其中包含了不需要映射的字段名。
  • keepGlobalFormat:保留全局配置的字段格式化功能。默认为 false。如果设置为 true,则保留全局配置的字段格式化功能

@TableField 注解用于配置数据库表字段与实体类字段之间的映射关系。它有多个属性,其中最常用的属性包括:

  1. value:该属性用于指定数据库表中的字段名,与实体类字段名进行映射。例如,@TableField("user_name") 表示 username 字段与数据库表中的 user_name 字段进行映射。
  2. exist:用于标识字段是否存在于数据库表中,默认为 true。如果设置为 false,MyBatis-Plus 在生成 SQL 语句时会忽略该字段,即不包括在查询条件中。
  3. el:用于设置字段在实体类中的 EL 表达式,用于动态生成 SQL。这个属性可以用来根据一些条件动态决定是否包含该字段。例如,@TableField(el = "activeFlag == 1") 表示只有当 activeFlag 等于 1 时,才包括该字段。
  4. typeHandler:用于指定字段类型处理器,可以自定义处理数据库字段与 Java 类型之间的转换。通常情况下,MyBatis-Plus 会自动选择合适的类型处理器,但你也可以通过这个属性来自定义处理器。
  5. fill:用于配置字段填充策略。字段填充是在插入和更新操作时,自动填充某些字段的值,例如创建时间和更新时间。你可以使用该属性来指定填充策略。

以上就是本期分享,希望对大家有帮助吧~

走过路过关注一波儿吧,感谢!

三连 的给个 三连 ,没三连的 给个点赞 也是美滋滋的,谢谢各位大佬。

我是无脑,点赞 + 在看 还是想求一下的,祝大家都能心想事成、发大财、行大运。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值