Spring Boot集成MyBatis-Plus持久层框架实现数据库连接,支持自定义增删改查、条件构造器、分页插件、代码生成。
简介 | MyBatis-Plus (baomidou.com)
1、快速整合MyBatis-Plus
第一步,在 pom.xml 中引入 starter。
1 | <dependency> |
第二步,使用 @MapperScan 注解扫描 mapper 文件。
1 |
ServiceAutoConfig 是单独的配置类,mapper 接口按照业务进行了分类,mapper.xml 放在 resources 目录下。
第三步,在 application.yml 文件中增加MyBatis-Plus 的统一配置。
1 | # mybatis 相关统一配置 |
将数据库表中的下划线命名方式 (underscore case)映射为 Java 对象中的驼峰命名方式(camel case)。例如,数据库 表中的列名为 user_name,对应的 Java 对象的属性名为 userName。
2、MyBatis-Plus的基本使用
2.1、Service CRUD
示例:比如说我们要保存一个文章的标签。
1 |
|
tagDao 是我们定义的数据访问对象(Data Access Object,简称 DAO),它继承自 MyBatis-Plus 提供的 ServiceImpl 类。 @Autowired 注解将 TagDao 自动注入到当前类 中。这是 Spring 提供的依赖注入(DI)功能,可以让我们在当前类中方便地使用 TagDao。
1 |
|
@Repository 注解:这是 Spring 提供的注解,用于标识这个类是一个数据访问层 (DAO)组件。Spring 会自动扫描并将其实例化为一个 Bean,方便在其他类中通过依赖 注入(DI)使用。
ServiceImpl 是 MyBatis-Plus 提供的一个抽象类,提供了通用的 CRUD 方法。泛型参数 意味着 TagDao 类 主要用于处理 TagDO 数据对象的数据库操作,并使用 TagMapper 接口定义的方法进行操作。
通过继承 ServiceImpl 类,TagDao 就可以使用 MyBatis-Plus 提供的通用 CRUD 方法,如 save、getById、updateById 等。这些方法已经实现了基本的数据库操作,通常无需自 己编写 SQL 语句。
参数 tagDO 是一个数据对象(Data Object,简称 DO),表示数据库中的 tag 表。
1 |
|
@Data 注解是 Lombok 提供的,用于自动生成类的 getter、setter、equals、 hashCode 和 toString 方法,简化了代码编写。
@EqualsAndHashCode(callSuper = true) 注解也是 Lombok 提供的注解, cal lSuper = true 表示要调用父类(BaseDO)的 equals 和 hashCode 方法。
BaseDO 是我们自定义的 DO 基类,实现了 Serializable 接口 ,并且定义了主键 id( @TableI d(type = IdType.AUTO) 表示自增长,是 MyBatis-Plus 提供的注解),创建时间 createTime和更新时间 updateTime。
1 |
|
@TableName(“tag”) 注解是 MyBatis-Plus 提供的注解,用于指定数据库表名。
另外定义了四个属性:tagName(标签名称)、tagType(标签类型)、status(状 态)和 deleted(是否删除)。这些属性对应数据库表中的列。
2.2、Mapper CRUD
MyBatis-Plus 除了提供 Service 的 CRUD, 还提供了基于 Mapper 的 CRUD。 通常一些特殊的增删改查是通过 MyBatis-Plus 的 Mapper CRUD 接口实现的。
示例:比如说我们要保存文章,可以通过下面这种方式。
1 |
|
articleDetailMapper 是我们在当前类中注入的一个 Mapper 接口,它继承自 MyBatis-Plus 的 BaseMapper 接口。
1 | public interface ArticleDetailMapper extends BaseMapper<ArticleDetailDO>{ |
1 | /** |
这样,articleDetailMapper 也就具备了基本的增删改查功能。
2.3、常用注解
@TableName | 用于指定数据库表名,通常在实体类(DO 或 Entity)上使用。例如: @TableName(“user”) 。 |
@TableId | 用于指定表中的主键字段。通常在实体类的主键属性上使用。例如: @ TableId(value = “id”, type = IdType.AUTO) ,其中 value 表示主键字段名, type 表示主键生成策略。 |
@TableField | 用于指定表中的非主键字段。可以用于实体类的属性上,以映射属 性和数据库字段。 |
@TableLogic | 用于指定逻辑删除字段。逻辑删除是指在数据库中标记某个记录已 删除,而不是真正地删除记录。例如: @TableLogic(value = “0”, delval = “1”) ,其中 value 表示未删除状态的默认值,delval 表示删除状态的值。 |
@Version | 用于指定乐观锁字段。乐观锁是一种并发控制策略,用于解决多个线程 同时修改同一条记录的问题。例如: @Version private Integer version; |
3、MyBatis-Plus查询
3.1、普通查询
MyBatis-Plus 的 BaseMapper 提供了多种查询方法,比如说根据 ID 查找文章是这样用的:
1 | ArticleDO article = baseMapper.selectById(articleId); |
除此之外,还有根据ID 批量查询的 selectBatchIds:
1 | baseMapper.selectBatchIds(Arrays.asList(1,2)); |
根据键值对查询的 selectByMap:
1 | Map<String, Object> map = new HashMap<>(); |
3.2、条件构造器
MyBatis-Plus 的 Wrapper 是一个条件构造器,用于简化复杂的 SQL 查询条件的构建。它 提供了一系列易于使用的 API,让你能够以链式编程的方式编写查询条件,而不需要手动编 写 SQL 语句。
示例:假如我们来查询这样一个结果,包含“j”且状态是已发布的标签。我们可以这样来构建条件构造器。
1 |
|
QueryWrapper:用于构建查询条件。它继承自 AbstractWrapper,提供了各种查询条件 的构建方法,如 eq, ne, gt, ge, lt, le, like, isNull, orderBy 等等。详细见:条件构造器 | MyBatis-Plus (baomidou.com)
但是,通过表的字段总感觉很不舒服,万一哪一天数据库表发生变化了怎么办呢?代码和数据库就不匹配了呀。 更优雅的做法是采用 Lambda 的方式,如下查询标签示例:
1 | public List<TagDTO> listOnlineTag(String key, PageParam pageParam) { |
①、可以通过 Wrappers.lambdaQuery() 静态方法创建一个 Lambda 条件构造器。
②、 eq(TagDO::getStatus, PushStatusEnum.ONLINE.getCode()) :表示查询条件 为 status 等于 PushStatusEnum.ONLINE 的值(即查询上线的标签)。
③、 eq(TagDO::getDeleted, YesOrNoEnum.NO.getCode()) :表示查询条件为 deleted 等于 YesOrNoEnum.NO 的值(即查询未删除的记录)。
④、 and(!StringUtils.isEmpty(key), v -> v.like(TagDO::getTagName, ke y)) :表示如果 key 不为空,则添加一个查询条件,要求 tag_name 包含 key。
⑤、 orderByDesc(TagDO::getId) :表示按照 id 字段降序排序。
⑥、 if (pageParam != null) { query.last(PageParam.getLimitSql(pagePara m)); } :如果 pageParam 不为 null,则添加分页参数。
这样的话,就可以和数据库的字段隔离开,完全通过代码的方式去查询。
3.3、MyBatis-Plus自定义SQL
MyBatis-Plus 支持自定义 SQL 语句,我们可以在 Mapper 接口中编写自定义 SQL 方法, 并使用注解添加自定义的 SQL 语句。
示例:微信登录的时候会执行这条 SQL 语句。
1 | public interface UserMapper extends BaseMapper<UserDO> { |
接口中定义了一个名为 getByThirdAccountId 的方法,它接收一个名为 accountId 的参 数。
该方法使用了 @Select 注解,这个注解用于编写自定义的 SQL 查询。 @Select 注解内的 SQL 语句是: select * from user where third_account_id = #{account_i d} limit 1
,它会根据传入的 account_id 参数查询 user 表中的记录。 同时,方法参数 accountId 使用了 @Param 注解,指定了参数在 SQL 语句中的名称为 account_id。这样,在执行 SQL 语句时,MyBatis 会将参数值替换到对应的位置上。
除此之外,可以使用 xml 的方式,用来定义一些复杂的 SQL。
比如说,我们要统计网站的 PV、UV,那么我们在 resources 目录下新建一个名为 QueryCountMapper.xml 的文件,内容如下:
1 |
|
①、在 resources 目录下的好处是,MyBatis-Plus 默认帮我们配置了 xml 的位置,这样我们就不需要在 application.yml 中再配置了。
②、该 XML 文件定义了一个RequestCountMapper 映射器,它包含三个自定义查询:getPvTotalCount、getPvDayList 和 getUvDayList。与com.github.paicoding.forum.service.statistics.repository.mapper.RequestCountMapper 相匹配。
1 | public interface RequestCountMapper extends BaseMapper<RequestCountDO> |
4、MyBatis-Plus主键策略
策略 | 含义 |
---|---|
IdType.AUTO | 自增策略,也就是说,在插入数据时,无需设置主键值,数据库会自动分配主键值,数据库表的 ID 会设置为 Auto Increment。 |
IdType.NONE | 无主键策略。表示不使用任何主键生成策略,主键值需要手动设置。 |
IdType.UUID | 使用 UUID 作为主键。插入数据时,MyBatis-Plus 会自动生成一个 UUID 值作为主键值。 |
IdType.ID_WORKER | 使用雪花算法生成分布式唯一 ID。插入数据时,MyBatis-Plus 会 自动生成一个雪花 ID 作为主键值。 |
1 | public class User { |