字节笔记本

2026年2月22日

HZERO Mybatis 增强组件使用指南

本文介绍 HZERO 平台的 Mybatis 增强组件,该组件基于猪齿鱼 choerodon-starter-mybatis-mapper 拓展,提供了分页、数据多语言、基于对象的 SQL 编写、数据防篡改等功能,帮助开发者更高效地进行数据库操作。

组件概述

组件编码:hzero-starter-mybatis-mapper

增强 ORM 框架 Mybatis 的数据库 DML 处理能力,支持分页、数据多语言、基于对象的 SQL 编写,数据防篡改等功能。

组件坐标

xml
<dependency>
    <groupId>org.hzero.starter</groupId>
    <artifactId>hzero-starter-mybatis-mapper</artifactId>
    <version>${hzero.starter.version}</version>
</dependency>

特性

  • 基于猪齿鱼 choerodon-starter-mybatis-mapper 组件拓展
  • 支持复杂条件查询
  • 扩展多语言支持
  • 添加数据防篡改功能
  • 添加数据加密存储功能
  • 添加唯一校验功能

CRUD 支持

新增支持

方法说明
int insert(T record)插入一条记录
int insertSelective(T record)插入一条记录,Bean 中 null 的字段不会被插入
int insertOptional(T record)插入一条记录,指定插入的列,插入前调用 OptionalHelper.optional() 方法
int insertList(List<T> recordList)批量插入

注意:如果主键名称不叫 id,需要在 mapper 中重新覆写该方法,在注解中声明主键名称:

java
@Options(useGeneratedKeys = true, keyProperty = "主键名称")
@InsertProvider(type = SpecialProvider.class, method = "dynamicSql")
int insertList(List<T> recordList);

更新支持

方法说明
int updateByPrimaryKey(T record)根据主键更新实体全部字段,null 值会被更新
int updateByPrimaryKeySelective(T record)根据主键更新属性不为 null 的值
int updateOptional(T record)更新一条记录,指定更新的列

删除支持

方法说明
int delete(T record)根据实体属性作为条件进行删除,查询条件使用等号
int deleteByPrimaryKey(Object key)根据主键字段进行删除

查询支持

方法说明
List<T> select(T record)根据实体中的属性值进行查询
List<T> selectAll()查询全表结果,慎用
T selectByPrimaryKey(Object key)根据主键字段进行查询
List<T> selectByIds(String ids)根据主键字符串进行查询
int selectCount(T record)根据实体中的属性查询总数
T selectOne(T record)根据实体中的属性进行查询,只能有一个返回值
List<T> selectByCondition(Object condition)根据 Condition 条件进行查询
int selectCountByCondition(Object condition)根据 Condition 条件进行查询总数
List<T> selectOptional(T condition, Criteria criteria)复杂查询,支持多表关联

Condition 查询示例

java
mapper.selectByCondition(
    org.hzero.mybatis.domian.Condition.builder(Entity.class)
        .andWhere(
            org.hzero.mybatis.util.Sqls.custom()
                .andEqualTo(FIELD1, VALUE1)
                .andLike(FIELD2, VALUE2)
        ).build()
);

多语言支持

功能说明

在业务处理中,经常会有一些数据需要做多语言支持,根据用户选择的语言来动态切换显示内容。使用多语言组件时,提供的查询方法会自动 join 多语言表,不必开发人员再去手写 SQL。

使用说明

  1. 创建多语言表:多语言表的表名需要在原表名的基础上增加 _tl,多语言表中需要包含对应表的主键、需要多语言的列,以及 lang varchar(30) 字段

  2. 实体类配置

    • 继承 io.choerodon.mybatis.domain.AuditDomain
    • 添加 @MultiLanguage 注解
    • 在对应的多语言列上添加 @MultiLanguageField 注解
  3. 数据格式:新增/更新数据时,实体类 JSON 中需要添加多语言 map:

json
{
    "_tls": {
        "roleName": {
            "zh_CN": "管理员",
            "en_GB": "Admin"
        },
        "description": {
            "zh_CN": "管理员",
            "en_GB": "administrator"
        }
    }
}
  1. 临时关闭多语言:调用 MultiLanguageHelper.close() 方法临时关闭多语言支持(一次 mybatis 操作后自动恢复,只在当前线程内生效)

数据防篡改

功能说明

数据从后端传输到前端之后,在进行更新操作时,经常需要对主键字段做校验,防止恶意篡改主键导致后端数据被破坏。数据防篡改功能将数据主键进行加密,进行数据更新时,对加密信息做校验用来验证主键信息有没有被篡改。

使用说明

  1. 实体类继承:继承 io.choerodon.mybatis.domain.AuditDomain
  2. VO/DTO 实现:实现 org.hzero.mybatis.domian.SecurityToken 接口
  3. 校验方法:在更新数据前调用 SecurityTokenHelper.validToken(..) 方法校验主键

数据加密存储

功能说明

有一些保密性比较强的信息需要加密之后保存到数据库,例如配置的用户的邮箱密码、某些其他服务的密钥等。在数据库做加密存储主要是防止数据库信息被盗取导致用户信息泄露。

使用说明

  1. 在需要加密的字段上添加 @DataSecurity 注解
  2. 在新增/更新数据之前,调用 DataSecurityHelper.open() 方法开启数据加密
  3. 在查询数据之前,调用 DataSecurityHelper.open() 方法开启解密
  4. 加密使用 AES 加密

租户条件过滤

功能说明

为了防止 SaaS 模式下的租户功能越权(查询到不属于自己租户的数据),在没有租户参数进行数据过滤控制的情况下,增加了后端通用过滤规则。

使用说明

注解模式(针对使用平台封装好的查询方法生效):

  • 在 Controller 类方法上添加 @TenantLimitedRequest 注解
  • 默认 SQL 拼装为 IN 模式:WHERE tenant_id IN (可访问租户ID列表)
  • 设置 TenantLimitedRequest(equal=true),SQL 拼装为 = 模式:WHERE tenant_id = (当前租户ID)

自定义 Mapper

xml
<!-- 获取可访问租户列表 -->
<bind name="__tenantIds" value="@org.hzero.mybatis.helper.TenantLimitedHelper@tenantIds()" />
<if test="__tenantIds != null and !__tenantIds.isEmpty()">
    and tenant_id in
    <foreach collection="__tenantIds" item="__tenantId" separator="," open="(" close=")">
        #{__tenantId}
    </foreach>
</if>

<!-- 获取当前租户 -->
<bind name="__tenantId" value="@org.hzero.mybatis.helper.TenantLimitedHelper@tenantId()" />
<if test="__tenantId != null">
    and tenant_id = #{__tenantId}
</if>

数据唯一校验

功能说明

在开发过程中,经常需要传到后端的数据在数据库中做唯一校验,该功能是对该需求的封装,旨在简化开发过程中重复的工作。

使用说明

  1. 在 Entity 需要校验唯一的字段上添加注解 @Unique
  2. 调用校验方法:UniqueHelper.valid(T),返回布尔值,true 表示校验通过
java
Assert.isTrue(UniqueHelper.valid(bank), BaseConstants.ErrorCode.DATA_EXISTS);

自定义主键策略

雪花 ID

雪花 ID 是 Twitter 推出的分布式全局唯一 ID 解决方案,相比于 UUID 有以下优点:

  • 按照时间有序生成
  • 长度最长为 19 位的数字(Long)
  • 效率较高,在整个分布式系统内不会产生碰撞

雪花 ID 结构

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
  • 第 1 位:符号位,固定为 0
  • 后 41 位:时间戳位,毫秒级,最多可使用约 69 年
  • 后 10 位:机器标识位,可部署 1024 个节点
  • 后 12 位:序列位,每毫秒支持每个节点生成 4096 个序号

配置属性

yaml
mybatis:
  configuration:
    key-generator: snowflake
    snowflake:
      start-timestamp: 1577808000000
      meta-provider: redis
      data-center-id: 1
      worker-id: 1

版本更新日志

0.8.0.RELEASE [2019-03-29]

  • 添加复杂查询 selectOptional
分享: