# Easy-Trans数据翻译

# 概述

平台集成了easy-trans,easy-trans是一款用于做数据翻译的代码辅助组件,利用mybatis plus框架的能力自动查表,让开发者可以快速的把id/字典码等翻译为前端需要展示的数据。

east-trans

# 适用场景

  • 存在一个id,需要给客户展示他的title/name,但是又不想手动做表关联查询
  • 存在一个字典码sex和一个字典值0,希望能翻译成给客户展示
  • 存在一组user id比如1,2,3,希望能展示成张三,李四,王五给客户
  • 存在一个唯一键(比如手机号,身份证号码,但是非其他表id字段),需要给客户展示他的title/name,但是又不想自己手动做表关联查询
  • 反向翻译场景,把用户名admin反向翻译为userid1,把反向翻译为gender_1

# 配置

# 添加maven依赖

<dependency>
    <groupId>com.mediway.hos</groupId>
    <artifactId>hos-framework-easytrans-starter</artifactId>
    <version>2.4.0及以上</version>
</dependency>

# 添加yml配置

easy-trans:
  #全局翻译开关,开启之后拦截所有responseBody进行自动翻译,如果对于性能要求很高可关闭此配置,默认为false
  is-enable-global: false
  #启用redis缓存 如果不用redis请设置为false
  is-enable-redis: true
  #启用平铺模式,非平铺模式下,翻译结果被封装在一个map中,平铺模式下,翻译结果与查询的对象处于平级,默认为false
  is-enable-tile: true
  #字典缓存放到redis 微服务模式下请开启
  dict-use-redis: true
  # 反向翻译数据库类型,完美支持mysql,postgresql,其他类型数据库慎用
  db-type: mysql

# 功能介绍

# 自动翻译和手动翻译

# 全局自动翻译

easy-trans.is-enable-global设置为true的时候,所有的responseBody框架都会拦截尝试翻译,支持嵌套。称之为全局自动翻译。

easy-trans:
  is-enable-global: true

如果想要排除一些结果不被翻译,可以在controller的方法上添加@IgnoreTrans注解进行排除

@IgnoreTrans
@GetMapping("/one")
public HttpResult<Student> student(){
	 return HttpResult.success(new Student());
}

# 翻译指定方法

easy-trans.is-enable-global设置为false的时候,可以在controller的方法上添加@TransMethodResult注解,就会自动翻译该方法return的值,原理是基于AOP进行实现。

@TransMethodResult
public Student getStudent(){
    Student student = new Student();
    student.setTeacherId(1);
    return student;
}

# 手动翻译

可以注入TransService然后调用transOne或者transBatch来翻译一个或者多个对象,称之为手动翻译,手动翻译不支持平铺。

@Autowired
private TransService transService;

@GetMapping("/one")
public HttpResult<Student> student(){
    Student student = new Student();
    student.setTeacherId(1);
    transService.transOne(student);
    return HttpResult.success(student);
}

@GetMapping("/list")
public HttpResult<List<Student>> studentList(){
    Student student1 = new Student();
    student1.setTeacherId(1);
    Student student2 = new Student();
    student2.setTeacherId(2);
    List<Student> studentList = new ArrayList<>();
    studentList.add(student1);
    studentList.add(student2);
    transService.transBatch(schoolList);
    return HttpResult.success(schoolList);
}

# 重点注解@Trans介绍

easy-trans有一个重要的注解@Trans,该注解总是放置在POJO/VO/DTO等类的属性字段上,表示该字段需要被翻译。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Trans {

    /**
     * 指定翻译的数据源,easy-trans支持多种数据源,所以要手动指定。 可选值:
     * TransType.SIMPLE 本服务/单体项目系统自动查表作为数据源
     * TransType.DICTIONARY 字典缓存作为数据源
     * TransType.RPC 自动调用其他微服务接口进行自动查表作为数据源
     * TransType.AUTO_TRANS 自定义数据源翻译
     *
     */
    String type();

    /**
     * 指定具体数据源(type为TransType.AUTO_TRANS或者TransType.DICTIONARY才需要配置)
     * type为TransType.AUTO_TRANS 传入自定义翻译源的namespace
     * type为TransType.DICTIONARY 传入字典分组编码 比如orderStatus
     *
     */
    String key() default "";

    /**
     * 将翻译出来的数据映射到本pojo的某个属性上
     * 比如根据userId翻译userName,vo中已经有userName了,可以通过ref对vo的username进行赋值。
     *
     */
    String ref() default "";

    /**
     * ref 支持多个,为了保持兼容新加了一个字段
     * 作用同ref 只是支持多个
     *
     */
    String[] refs() default {};

    /**
     * 目标class
     *
     */
    Class<? extends VO> target() default TransPojo.class;

    /**
     * 用来指定需要对方类的哪个/哪些字段(TransType.SIMPLE和TransType.RPC可用),支持指定多个
     *
     */
    String[] fields() default {};

    /**
     * 别名,解决翻译结果字段名重名问题
     * 一个vo有createUserId和updateUserId 他们的结果都叫userName 就可以通过别名来区分,比如updateUserId的alias配置为update 那么结果就为updateUserName,是一个拼接的结果
     *
     */
    String alias() default "";

    /**
     * 微服务名称(TransType.RPC有效)
     * TransType.RPC的时候组件自动调用其他微服务的接口获取数据,所以要指定服务名称,easyTrans会自动去注册中心获取对应的服务实例URL进行调用。
     *
     */
    String serviceName() default "";

    /**
     * 服务的context-path
     * 如果远程微服务配置了context-path 可以通过此属性来配置,保证RPC调用不会404
     *
     */
    String serviceContextPath() default "";

    /**
     * 目标类全类名(TransType.SIMPLE和TransType.RPC可用)
     */
    String targetClassName() default "";

    /**
     * 自定义的函数名(此名称需要被spring托管 并实现FuncGetter)
     * 
     */
    String customeBeanFuncName() default "";

    /**
     * 数据源名称
     * 在多数据源环境下指定此翻译使用哪个数据源 TransType.SIMPLE 有效。
     * 
     */
    String dataSource() default "";

    /**
     * 唯一键字段
     * vo中的属性不是对方的id,而是唯一键,这里就是配置目标类的唯一键的字段名(TransType.RPC和TransType.SIMPLE可用)
     * 注意:不支持同一个类中混用id和唯一键,比如:Student类中有createUserId 和 updateUserMobile(用户的唯一键字段)
     * 
     */
    String uniqueField() default "";

    /**
     * 翻译顺序
     * 比如 文章表有createBy 字段 对应用户表 用户表有orgid字段对应 组织表。 文章vo需要展示创建人以及创建人所在部门。 就可以指定sort 先对createBy字段进行翻译,取orgid用ref设置到文章vo上,然后再用orgid翻译org的名称。
     * 
     */
    int sort() default 0;
}

# 接口TransPojo介绍

实现TransPojo接口的类,代表这个类需要被翻译或者被当作翻译的数据源。例如合同实体类Contract如果想要被翻译或者作为翻译其他实体类的数据源,就需要实现TransPojo接口

@Data
public class Contract implements TransPojo {
    
}

# 支持的四种翻译类型

easy-trans支持四种翻译类型,分别为简单翻译字典翻译跨微服务翻译以及自定义数据源翻译四种类型,下边进行详细介绍。

# 1.简单翻译(TransType.SIMPLE)

当存在xxxId或唯一标识字段作为其他表主键或唯一键,例如存在userId,需要将其他表属性如userName返给前端时就可使用该模式,该模式的原理是组件使用MybatisPlus的API自动进行查询,把结果放到transMap中。 使用时只需要在翻译的字段上添加下面一个注解,指定typeTransType.SIMPLE,指定目标类target以及要获取目标类的哪个属性fields即可。

@Trans(type = TransType.SIMPLE, target = Users.class, fields = "userName")
private String userId;

# 2.字典翻译(TransType.DICTIONARY)

如果要将users表中的性别gender字段进行翻译,gender为0时翻译成男,gender为1时翻译成女,这个时候我们可以使用字典翻译。字典翻译需要使用者提前把字典信息刷新到DictionaryTransService中进行缓存,在进行字典翻译时会取缓存作为翻译数据源。 可以在系统启动的时候初始化字典,字典的数据在哪获取easy-trans并不关心,json、properties、微服务、数据库均是可以的。字典翻译时需要指定typeTransType.DICTIONARY,同时指定字典分组编码作为key

// 初始化字典缓存
@Component
public class EasyTransDictConfig implements InitializingBean {
    //注入字典翻译服务
    @Autowired
    private DictionaryTransService dictionaryTransService;

    @Override
    public void afterPropertiesSet() throws Exception {
        //将字典缓存刷新到翻译服务中
        Map<String,String> transMap = new HashMap<>();
        transMap.put("1","男");
        transMap.put("2","女");
        dictionaryTransService.refreshCache("gender",transMap);
    }
}
// 指定翻译字段
@Trans(type = TransType.DICTIONARY, key = "gender", fields = "genderName")
private Integer gender;

# 3.自定义数据源翻译(TransType.AUTO_TRANS)

存在根据id翻译name场景,但是使用者如果想组件调用自己写的方法而不是通过Mybatis Plus的API进行数据查询,就可以使用自定义数据源模式AutoTrans(如果系统使用了Mybatis Plus,则AutoTrans模式不建议使用,而是强烈建议使用SIMPLE模式)。

自定义数据源之前首先需要介绍其中一个重要注解@AutoTrans@AutoTrans注解标记到数据源提供类上,提供了一些默认配置,参数如下:

序号 属性 默认值 备注
1 namespace 与@Trans(key="xx")对应
2 fields 返回的对象中哪些字段需要做翻译结果
3 defaultAlias 别名,比如Teacher表的name字段如果配置了别名teacher,翻译结果为:teacherName
4 globalCache false 全局缓存,默认关闭
5 isAccess false 开启全局缓存后,缓存失效时间计算规则,配置false按照缓存加入时间算,true按照最后一次访问时间算
6 cacheSeconds 1 缓存时间,默认1秒
7 maxCache 1000 最大缓存对象数量

自定义的数据源类上需要加上@AutoTrans注解,并且需要实现AutoTransable接口,该接口包含3个方法:selectByIds用于查询集合,selectById用于查询单个对象,select用于查询全部对象,其中select做个空实现即可。

@Service
@AutoTrans(namespace = "customer",fields = {"customerName","phone"},
        defaultAlias = "customer", globalCache = true, cacheSeconds = 10, maxCache = 100)
public class HosCustomerServiceImpl implements AutoTransable<HosCustomer> {

    @Override
    public List<HosCustomer> selectByIds(List<?> ids) {
        log.info("HosCustomerServiceImpl.selectByIds invoke,ids:{}", ids);
        List<HosCustomer> customerList = new ArrayList<>();
        for (Object id : ids) {
            // 编写自定义根据ids获取顾客list的逻辑代码
            HosCustomer hosCustomer = new HosCustomer();
            hosCustomer.setId(String.valueOf(id));
            hosCustomer.setCustomerName("张三");
            hosCustomer.setPhone("13111111111");
            customerList.add(hosCustomer);
        }
        return customerList;
    }

    @Override
    public List<HosCustomer> select() {
        log.info("HosCustomerServiceImpl.select invoke");
        return new ArrayList<>();
    }

    @Override
    public HosCustomer selectById(Object primaryValue) {
        log.info("HosCustomerServiceImpl.selectById invoke,primaryValue:{}", primaryValue);
        // 编写自定义根据id获取顾客的逻辑代码
        HosCustomer hosCustomer = new HosCustomer();
        hosCustomer.setId(String.valueOf(primaryValue));
        hosCustomer.setCustomerName("13222222222");
        hosCustomer.setPhone("李四");
        return hosCustomer;
    }
}

# 4.跨微服务翻译(TransType.RPC)

如果想要跨微服务间进行翻译,可以使用该模式。例如存在订单和用户2个服务,如果想要在订单详情里展示订单的创建人的用户名,就需要用到RPC翻译,原理是订单服务使用restTemplate调用用户服务的一个统一的接口,把需要翻译的id传过去,然后用户服务使用MybatisPlus的API自动进行查询把结果返回给订单服务。 使用RPC模式,需要指定@TranstypeTransType.RPC,并且指定目标翻译类的全类名targetClassName,指定对方微服务的服务名serviceName,注解其余属性参考SIMPLE用法即可。

@ApiModelProperty(value = "合同签订者")
@Trans(type = TransType.RPC, targetClassName = "com.mediway.oa.user.model.entity.Staff",fields = "phone",ref = "signerPhone", serviceName = "oa-user-service",uniqueField = "name")
private String signer;

@ApiModelProperty(value = "合同签订者手机号")
private String signerPhone;

提示

1.微服务模式下,推荐将字典数据放到redis中去,避免各服务的字典缓存出现不一致情况。
2.微服务模式的实现原理是通过一个控制器暴漏出接口给消费者调用,所以一定要保证服务A调用服务B的/easyTrans/proxy/*可以调用通,如果系统中使用了权限框架拦截,一定要对该请求放行。

# 缓存使用

# 1.缓存开启

# 1.1.字典缓存

字典默认使用hashmap来存放缓存,同时也支持使用redis来进行缓存,这样内存中没有的时候会自动去redis里面找,然后放到内存中,解决了微服务的字典问题,也保证了性能。 开启方式:

easy-trans:
  dict-use-redis : true 

# 1.2.SIMPLE翻译缓存

可以使用注解@TransDefaultSett来开启SIMPLE的缓存功能,只需要给数据源类上加@TransDefaultSett(isUseCache = true) 即可。 可选参数:

  • isUseCache 是否开启缓存,默认为false
  • cacheSeconds 缓存失效时间,单位秒,默认5
  • maxCache 最大缓存数量,默认为1000
  • isAccess 默认false,设置为true的话会按照最后一次访问时间进行缓存过期计时,false按照添加时间计时

# 1.3.RPC翻译缓存

在配置类上添加:

@Configuration
public class EasyTransRpcCacheConfiguration implements InitializingBean {

    @Autowired
    private TransCacheManager transCacheManager;

    @Override
    public void afterPropertiesSet() throws Exception {
        transCacheManager.setRpcTransCache("com.mediway.oa.user.model.entity.Staff",
                SimpleTransService.TransCacheSett.builder().cacheSeconds(20).maxCache(1000).build());
    }
}

上面这段代码要配置到消费者对应微服务中,比如Order中要翻译userId,order和user是2个微服务,要把代码放到order微服务里,而不是user微服务。 SimpleTransService.TransCacheSett使用build构造的时候默认值不起作用,会导致缓存配置不起作用,所以cacheSeconds和maxCache都要手动指定。

# 2.缓存刷新/清理

# 2.1.字典缓存

在微服务模式下,如果修改了某个字典,可以通过以下方式刷新各个微服务字典,执行完代码后,easy-trans会刷新redis的缓存,然后清理掉各个微服务的内存缓存,重新获取redis中的缓存。

Map<String,String> transMap = new HashMap<>();
transMap.put("0","男");
transMap.put("1","女");
dictionaryTransService.refreshCacheAndNoticeOtherService("gender",transMap);

# 2.2.SIMPLE/RPC模式的翻译缓存清理

通过下面代码可清理掉本微服务和其他微服务的所有跟User相关的SIMPLE和RPC缓存。 PS:如果要清理掉其他微服务的RPC缓存,需要使用Redis,因为是用redis做了广播去清理。

@Autowired
private TransCacheManager transCacheManager;
transCacheManager.clearCache(User.class,"1");

# 级联翻译

如果存在级联翻译的场景,比如存在一个城市id,如果想要通过城市id拿到省份id进而获取到省份名称,就可以使用级联翻译。级联翻译同样使用TransType.SIMPLE模式,只是需要将通过城市id查到的省份id再次进行翻译查到省份名称,同时需要指定顺序sort,序号越小越先执行。

@ApiModelProperty(value = "生产地城市id")
@Trans(type = TransType.SIMPLE, target = HosCity.class, fields = {"name","provinceId"}, refs = {"productCityName","productProvinceId"}, sort = 0)
private String productCityId;

@ApiModelProperty(value = "生产地城市名称")
private String productCityName;

@ApiModelProperty(value = "生产地省份id")
@Trans(type = TransType.SIMPLE, target = HosProvince.class, fields = "name", ref = "productProvinceName", sort = 1)
private String productProvinceId;

@ApiModelProperty(value = "生产地省份名称")
private String productProvinceName;

提示

1.SIMPLE和RPC模式只支持翻译单个对象,不支持翻译集合,dict模式均支持。
2.不同翻译类型混合使用时,优先级为RPC->SIMPLE->DICT。即由RPC或者SIMPLE的结果字段进行字典翻译是支持的,但是字典的翻译结果进行RPC或者SIMPLE翻译就不支持。

# 反向翻译

如果存在反向翻译的场景,比如已知一个城市名称想要查询城市id,或者已知商品的单价和名称想要查询商品的id,这两种场景就可使用反向翻译。 反向翻译需要将@UnTrans注解放到将要查询的字段身上,type支持UnTransType.DICTIONARY和UnTransType.SIMPLE两种模式。 注意:反向翻译只能使用手动翻译的方式。

// 根据已知的性别名称获取性别类型
private String genderName = "男;

@UnTrans(type=UnTransType.DICTIONARY,dict="gender",refs = {"genderName"})
private Integer gender;
// 根据已知的生产地城市名称查询生产地城市id
// 拼接后的sql为SELECT name AS groupKey,id as uniqueKey FROM hos_city WHERE name IN (xxx)
@ApiModelProperty(value = "生产地城市id")
@UnTrans(type= UnTransType.SIMPLE,tableName = "hos_city",refs = "productCityName",columns = "name",uniqueColumn = "id")
private String productCityId;

@ApiModelProperty(value = "生产地城市名称")
private String productCityName;

// 根据已知的商品名称和商品单价查询商品id
// 拼接后的sql为SELECT CONCAT(goods_name,'/',goods_price) AS groupKey,id as uniqueKey FROM hos_goods WHERE CONCAT(goods_name,'/',goods_price) IN (xxx)
@ApiModelProperty(value = "商品id")
@UnTrans(type= UnTransType.SIMPLE,tableName = "hos_goods",refs = {"goodsName","goodsPrice"},columns = {"goods_name","goods_price"},uniqueColumn = "id")
private String goodId;

@ApiModelProperty(value = "商品名称")
private String goodsName;

@ApiModelProperty(value = "商品单价")
private BigDecimal goodsPrice;

如果需要多张表关联查询,反向翻译可以在tableName中写join关联语句,同时在columns查询字段和uniqueColumn唯一键字段加上表的别名,如根据商品名称和生产地城市名称关联查询出生产地所属的省份id

// 执行sql:SELECT CONCAT(g.goods_name,'/',c.name) AS groupKey,c.province_id as uniqueKey FROM hos_goods g left join hos_city c on g.product_city_id = c.id WHERE CONCAT(g.goods_name,'/',c.name) IN
@ApiModelProperty(value = "生产地省份id")
@UnTrans(type= UnTransType.SIMPLE,tableName = "hos_goods g left join hos_city c on g.product_city_id = c.id",refs = {"goodsName","productCityName"},columns = {"g.goods_name","c.name"},uniqueColumn = "c.province_id")
private String productProvinceId;

@ApiModelProperty(value = "商品名称")
private String goodsName;

@ApiModelProperty(value = "生产地城市名称")
private String productCityName;

# 使用示例

# 前期准备

1.执行下面脚本,创建示例表和初始化数据

CREATE TABLE `hos_order` (
  `id` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
  `order_name` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '订单名称',
  `order_price` decimal(20,2) DEFAULT NULL COMMENT '订单总价',
  `good_id` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '商品id',
  `customer_id` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '顾客id',
  `gender` smallint DEFAULT NULL COMMENT '顾客性别',
  `order_status` smallint DEFAULT NULL COMMENT '订单状态',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='订单表';
insert into `hos_order` (`id`, `order_name`, `order_price`, `good_id`, `customer_id`, `gender`, `order_status`, `create_time`, `update_time`) values('1','汽车订单','260000.00','3','e5ce60d54694412b684c37b54b857584','1','1','2023-06-28 17:51:10','2023-06-29 11:41:14');
insert into `hos_order` (`id`, `order_name`, `order_price`, `good_id`, `customer_id`, `gender`, `order_status`, `create_time`, `update_time`) values('2','篮球订单','100.00','2','8f33bd0d85cc124c5193c29ae36242a2','2','2','2023-06-28 17:51:52','2023-06-29 11:41:52');
insert into `hos_order` (`id`, `order_name`, `order_price`, `good_id`, `customer_id`, `gender`, `order_status`, `create_time`, `update_time`) values('3','书包订单','20.00','1','8f33bd0d85cc124c5193c29ae36242a2','1','1','2023-06-28 17:52:21','2023-06-29 11:41:54');


CREATE TABLE `hos_goods` (
  `id` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
  `goods_name` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '商品名称',
  `goods_price` decimal(20,2) DEFAULT NULL COMMENT '商品单价',
  `product_city_id` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '生产地城市id',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='商品表';
insert into `hos_goods` (`id`, `goods_name`, `goods_price`, `product_city_id`, `create_time`, `update_time`) values('1','书包','20.00','111','2023-06-28 17:50:09','2023-06-29 15:35:01');
insert into `hos_goods` (`id`, `goods_name`, `goods_price`, `product_city_id`, `create_time`, `update_time`) values('2','篮球','50.00','222','2023-06-28 17:50:24','2023-06-29 15:35:02');
insert into `hos_goods` (`id`, `goods_name`, `goods_price`, `product_city_id`, `create_time`, `update_time`) values('3','汽车','260000.00','333','2023-06-28 17:50:35','2023-06-29 15:35:05');


CREATE TABLE `hos_order_status` (
  `id` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
  `order_status` smallint DEFAULT NULL COMMENT '订单状态',
  `order_status_desc` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '状态描述',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='订单状态表';
insert into `hos_order_status` (`id`, `order_status`, `order_status_desc`, `create_time`, `update_time`) values('140053e4a604406ea365973a315f95fb','3','已收货','2023-06-29 16:04:08','2023-06-29 16:04:08');
insert into `hos_order_status` (`id`, `order_status`, `order_status_desc`, `create_time`, `update_time`) values('1b22513aa18cc25180c1e0166d26db71','2','待发货','2023-06-29 16:03:55','2023-06-29 16:04:11');
insert into `hos_order_status` (`id`, `order_status`, `order_status_desc`, `create_time`, `update_time`) values('f84fc273f6925837d2b04a91a22ec3b9','1','待支付','2023-06-29 16:03:28','2023-06-29 16:03:43');


CREATE TABLE `hos_province` (
  `id` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
  `code` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '省份编码',
  `name` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '省份名称',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='省份表';
insert into `hos_province` (`id`, `code`, `name`, `create_time`, `update_time`) values('111111','bj','北京市','2023-06-29 15:44:06','2023-06-29 15:44:06');
insert into `hos_province` (`id`, `code`, `name`, `create_time`, `update_time`) values('222222','gd','广东省','2023-06-29 15:44:18','2023-06-29 15:44:18');
insert into `hos_province` (`id`, `code`, `name`, `create_time`, `update_time`) values('333333','hb','湖北省','2023-06-29 15:44:32','2023-06-29 15:44:32');


CREATE TABLE `hos_city` (
  `id` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键',
  `code` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '城市编码',
  `name` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '城市名称',
  `province_id` varchar(75) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '所属省份id',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='城市表';
insert into `hos_city` (`id`, `code`, `name`, `province_id`, `create_time`, `update_time`) values('111','bj','北京市','111111','2023-06-29 15:41:54','2023-06-29 15:41:54');
insert into `hos_city` (`id`, `code`, `name`, `province_id`, `create_time`, `update_time`) values('222','gz','广州市','222222','2023-06-29 15:43:15','2023-06-29 15:43:15');
insert into `hos_city` (`id`, `code`, `name`, `province_id`, `create_time`, `update_time`) values('333','wh','武汉市','333333','2023-06-29 15:43:42','2023-06-29 15:43:42');

2.为上述表生成相应的entity、service、serviceImpl、mapper、mapper.xml、以及controller

//entity
@Data
@ApiModel(value="HosOrder对象", description="订单表")
@TableName("hos_order")
public class HosOrder {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "订单名称")
    @TableField("order_name")
    private String orderName;

    @ApiModelProperty(value = "订单总价")
    @TableField("order_price")
    private BigDecimal orderPrice;

    @ApiModelProperty(value = "商品id")
    @TableField("good_id")
    private String goodId;

    @ApiModelProperty(value = "顾客id")
    @TableField("customer_id")
    private String customerId;

    @ApiModelProperty(value = "顾客性别")
    @TableField("gender")
    private Integer gender;

    @ApiModelProperty(value = "订单状态")
    @TableField("order_status")
    private Integer orderStatus;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

@Data
@ApiModel(value="HosGoods对象", description="商品表")
@TableName("hos_goods")
public class HosGoods {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "商品名称")
    @TableField("goods_name")
    private String goodsName;

    @ApiModelProperty(value = "商品单价")
    @TableField("goods_price")
    private BigDecimal goodsPrice;

    @ApiModelProperty(value = "生产地城市id")
    @TableField("product_city_id")
    private String productCityId;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

@Data
@ApiModel(value="HosOrderStatus对象", description="订单状态表")
@TableName("hos_order_status")
public class HosOrderStatus {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId("id")
    private String id;

    @ApiModelProperty(value = "订单状态")
    @TableField("order_status")
    private Integer orderStatus;

    @ApiModelProperty(value = "状态描述")
    @TableField("order_status_desc")
    private String orderStatusDesc;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_time")
    private Date createTime;

    @ApiModelProperty(value = "修改时间")
    @TableField("update_time")
    private Date updateTime;
}

@Data
@ApiModel(value="HosProvince对象", description="省份表")
@TableName("hos_province")
public class HosProvince {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId("id")
    private String id;

    @ApiModelProperty(value = "省份编码")
    @TableField("code")
    private String code;

    @ApiModelProperty(value = "省份名称")
    @TableField("name")
    private String name;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_time")
    private Date createTime;

    @ApiModelProperty(value = "修改时间")
    @TableField("update_time")
    private Date updateTime;
}

@Data
@ApiModel(value="HosCity对象", description="城市表")
@TableName("hos_city")
public class HosCity {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId("id")
    private String id;

    @ApiModelProperty(value = "城市编码")
    @TableField("code")
    private String code;

    @ApiModelProperty(value = "城市名称")
    @TableField("name")
    private String name;

    @ApiModelProperty(value = "所属省份id")
    @TableField("province_id")
    private String provinceId;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_time")
    private Date createTime;

    @ApiModelProperty(value = "修改时间")
    @TableField("update_time")
    private Date updateTime;
}


//service
public interface HosOrderService extends BaseService<HosOrder> {

}

public interface HosGoodsService extends BaseService<HosGoods> {

}

public interface HosOrderStatusService extends BaseService<HosOrderStatus> {

}

public interface HosProvinceService extends BaseService<HosProvince> {

}

public interface HosCityService extends BaseService<HosCity> {

}
//serviceImpl
@Service
public class HosOrderServiceImpl extends BaseServiceImpl<HosOrderMapper, HosOrder> implements HosOrderService {

}

@Service
public class HosGoodsServiceImpl extends BaseServiceImpl<HosGoodsMapper, HosGoods> implements HosGoodsService {

}

@Service
public class HosOrderStatusServiceImpl extends BaseServiceImpl<HosOrderStatusMapper, HosOrderStatus> implements HosOrderStatusService {

}

@Service
public class HosProvinceServiceImpl extends BaseServiceImpl<HosProvinceMapper, HosProvince> implements HosProvinceService {

}

@Service
public class HosCityServiceImpl extends BaseServiceImpl<HosCityMapper, HosCity> implements HosCityService {

}
//mapper
public interface HosOrderMapper extends BaseMapper<HosOrder> {

}

public interface HosGoodsMapper extends BaseMapper<HosGoods> {

}

public interface HosOrderStatusMapper extends BaseMapper<HosOrderStatus> {

}

public interface HosProvinceMapper extends BaseMapper<HosProvince> {

}

public interface HosCityMapper extends BaseMapper<HosCity> {

}

//启动类别忘了添加扫描mapper注解,保证可以扫描到mapper包
@ServletComponentScan(basePackages = "com.mediway")
@MapperScan(basePackages = {"com.mediway.oa.**.mapper"})
@SpringBootApplication
public class HosApplication {
    public static void main(String[] args) {
        SpringApplication.run(HosApplication.class, args);
    }
}


HosOrderMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mediway.oa.easytrans.mapper.HosOrderMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.mediway.oa.easytrans.model.entity.HosOrder">
    <result column="id" property="id" />
    <result column="create_time" property="createTime" />
    <result column="update_time" property="updateTime" />
        <result column="order_name" property="orderName" />
        <result column="order_price" property="orderPrice" />
        <result column="good_id" property="goodId" />
        <result column="gender" property="gender" />
        <result column="order_status" property="orderStatus" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id,
        create_time,
        update_time,
        order_name, order_price, good_id, gender, order_status
    </sql>
</mapper>

HosGoodsMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mediway.oa.easytrans.mapper.HosGoodsMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.mediway.oa.easytrans.model.entity.HosGoods">
    <result column="id" property="id" />
    <result column="create_time" property="createTime" />
    <result column="update_time" property="updateTime" />
        <result column="goods_name" property="goodsName" />
        <result column="goods_price" property="goodsPrice" />
        <result column="product_city_id" property="productCityId" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id,
        create_time,
        update_time,
        goods_name, goods_price, product_city_id
    </sql>
</mapper>

HosOrderStatusMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mediway.oa.easytrans.mapper.HosOrderStatusMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.mediway.oa.easytrans.model.entity.HosOrderStatus">
        <id column="id" property="id" />
        <result column="order_status" property="orderStatus" />
        <result column="order_status_desc" property="orderStatusDesc" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, order_status, order_status_desc, create_time, update_time
    </sql>
</mapper>

HosProvinceMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mediway.oa.easytrans.mapper.HosProvinceMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.mediway.oa.easytrans.model.entity.HosProvince">
        <id column="id" property="id" />
        <result column="code" property="code" />
        <result column="name" property="name" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, code, name, create_time, update_time
    </sql>
</mapper>

HosCityMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mediway.oa.easytrans.mapper.HosCityMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.mediway.oa.easytrans.model.entity.HosCity">
        <id column="id" property="id" />
        <result column="code" property="code" />
        <result column="name" property="name" />
        <result column="province_id" property="provinceId" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, code, name, province_id, create_time, update_time
    </sql>
</mapper>

//controller
@RestController
@RequestMapping("hosOrder")
@Api(tags = "订单表")
public class HosOrderController {

    @Autowired
    private HosOrderService orderService;

}

@RestController
@RequestMapping("hosGoods")
@Api(tags = "商品表")
public class HosGoodsController {

    @Autowired
    private HosGoodsService goodsService;

}

@RestController
@RequestMapping("hosOrderStatus")
@Api(tags = "订单状态表")
public class HosOrderStatusController {

}

@RestController
@RequestMapping("hosProvince")
@Api(tags = "省份表")
public class HosProvinceController {

}

@RestController
@RequestMapping("hosCity")
@Api(tags = "城市表")
public class HosCityController {

}

# SIMPLE模式使用

查询订单详情列表,订单详情中含有商品id,模拟根据商品id查询商品名称和商品价格

1.订单表实体类实现TransPojo接口,在goodId字段上加上@Trans注解,指定要查询HosGoods类的goodsNamegoodsPrice,并将查询后的值赋给本类中的goodsNamegoodsPrice字段。

@Data
@ApiModel(value="HosOrder对象", description="订单表")
@TableName("hos_order")
public class HosOrder implements TransPojo {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "订单名称")
    @TableField("order_name")
    private String orderName;

    @ApiModelProperty(value = "订单总价")
    @TableField("order_price")
    private BigDecimal orderPrice;

    @ApiModelProperty(value = "商品id")
    @TableField("good_id")
    @Trans(type = TransType.SIMPLE, target = HosGoods.class, fields = {"goodsName","goodsPrice"}, refs = {"goodsName","goodsPrice"}) //翻译多个字段
    //@Trans(type = TransType.SIMPLE, target = HosGoods.class, fields = "goodsName", refs = "goodsName") //翻译单个字段
    private String goodId;

    @ApiModelProperty(value = "商品名称")
    @TableField(exist = false)
    private String goodsName;

    @ApiModelProperty(value = "商品单价")
    @TableField(exist = false)
    private String goodsPrice;

    @ApiModelProperty(value = "顾客id")
    @TableField("customer_id")
    private String customerId;

    @ApiModelProperty(value = "顾客性别")
    @TableField("gender")
    private Integer gender;

    @ApiModelProperty(value = "订单状态")
    @TableField("order_status")
    private Integer orderStatus;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

2.商品表实体类实现TransPojo接口

@Data
@ApiModel(value="HosGoods对象", description="商品表")
@TableName("hos_goods")
public class HosGoods implements TransPojo {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "商品名称")
    @TableField("goods_name")
    private String goodsName;

    @ApiModelProperty(value = "商品单价")
    @TableField("goods_price")
    private BigDecimal goodsPrice;

    @ApiModelProperty(value = "生产地城市id")
    @TableField("product_city_id")
    private String productCityId;

    @ApiModelProperty(value = "生产地省份id")
    @TableField(exist = false)
    private String productProvinceId;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

3.HosOrderController添加接口,采用@TransMethodResult进行翻译

@RestController
@RequestMapping("hosOrder")
@Api(tags = "订单表")
public class HosOrderController {

    @Autowired
    private HosOrderService orderService;

    @TransMethodResult
    @GetMapping("/selectOrderList")
    public BaseResponse<List<HosOrder>> selectOrderList() {
        return BaseResponse.success(orderService.list());
    }
}

4.请求接口

url:http://localhost:8007/hosOrder/selectOrderList
RequestMethod:GET

返回结果如下,可以看到goodsNamegoodsPrice同样也被查询显示出来

{
    "code": "200",
    "msg": "操作成功",
    "data": [
        {
            "id": "1",
            "orderName": "汽车订单",
            "orderPrice": 260000.00,
            "goodId": "3",
            "goodsName": "汽车",
            "goodsPrice": "260000.00",
            "customerId": "e5ce60d54694412b684c37b54b857584",
            "gender": 1,
            "orderStatus": 1,
            "createTime": "2023-06-28 17:51:10",
            "updateTime": "2023-06-29 11:41:14"
        },
        {
            "id": "2",
            "orderName": "篮球订单",
            "orderPrice": 100.00,
            "goodId": "2",
            "goodsName": "篮球",
            "goodsPrice": "50.00",
            "customerId": "8f33bd0d85cc124c5193c29ae36242a2",
            "gender": 2,
            "orderStatus": 2,
            "createTime": "2023-06-28 17:51:52",
            "updateTime": "2023-06-29 11:41:52"
        },
        {
            "id": "3",
            "orderName": "书包订单",
            "orderPrice": 20.00,
            "goodId": "1",
            "goodsName": "书包",
            "goodsPrice": "20.00",
            "customerId": "8f33bd0d85cc124c5193c29ae36242a2",
            "gender": 1,
            "orderStatus": 1,
            "createTime": "2023-06-28 17:52:21",
            "updateTime": "2023-06-29 11:41:54"
        }
    ],
    "success": true
}

控制台打印日志,可见在查询主表同时自动查询了翻译数据源表商品表

east-trans-2

SIMPLE模式使用缓存,在商品表实体类上加上注解@TransDefaultSett

@Data
// 设置SIMPLE缓存
@TransDefaultSett(isUseCache = true, cacheSeconds = 20)
@ApiModel(value="HosGoods对象", description="商品表")
@TableName("hos_goods")
public class HosGoods implements TransPojo {
    
}

再次请求接口之后观察控制台打印日志如下,只查询了一次主表,翻译数据源没有再次查询,可见缓存生效

east-trans-3

# DOCTIONARY模式使用

1.创建字典配置类初始化字典项

@Component
public class EasyTransDictConfig implements InitializingBean {
    //注入字典翻译服务
    @Autowired
    private DictionaryTransService dictionaryTransService;

    @Override
    public void afterPropertiesSet() throws Exception {
        //将字典缓存刷新到翻译服务中
        Map<String,String> transMap = new HashMap<>();
        transMap.put("1","男");
        transMap.put("2","女");
        dictionaryTransService.refreshCache("gender",transMap);
    }
}

2.订单表实体类实现TransPojo接口,在gender字段上加上@Trans注解

@Data
@ApiModel(value="HosOrder对象", description="订单表")
@TableName("hos_order")
public class HosOrder implements TransPojo {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "订单名称")
    @TableField("order_name")
    private String orderName;

    @ApiModelProperty(value = "订单总价")
    @TableField("order_price")
    private BigDecimal orderPrice;

    @ApiModelProperty(value = "商品id")
    @TableField("good_id")
    @Trans(type = TransType.SIMPLE, target = HosGoods.class, fields = {"goodsName","goodsPrice"}, refs = {"goodsName","goodsPrice"}) //翻译多个字段
    //@Trans(type = TransType.SIMPLE, target = HosGoods.class, fields = "goodsName", refs = "goodsName") //翻译单个字段
    private String goodId;

    @ApiModelProperty(value = "商品名称")
    @TableField(exist = false)
    private String goodsName;

    @ApiModelProperty(value = "商品单价")
    @TableField(exist = false)
    private String goodsPrice;

    @ApiModelProperty(value = "顾客id")
    @TableField("customer_id")
    private String customerId;

    @ApiModelProperty(value = "顾客性别")
    @TableField("gender")
    @Trans(type = TransType.DICTIONARY, key = "gender", fields = "genderName")
    private Integer gender;

    @ApiModelProperty(value = "订单状态")
    @TableField("order_status")
    private Integer orderStatus;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

3.HosOrderController添加接口,采用@TransMethodResult进行翻译

@RestController
@RequestMapping("hosOrder")
@Api(tags = "订单表")
public class HosOrderController {

    @Autowired
    private HosOrderService orderService;

    @TransMethodResult
    @GetMapping("/selectOrderList")
    public BaseResponse<List<HosOrder>> selectOrderList() {
        return BaseResponse.success(orderService.list());
    }
}

4.请求接口

url:http://localhost:8007/hosOrder/selectOrderList
RequestMethod:GET

返回结果如下,可以看到genderName也被查询显示出来

{
    "code": "200",
    "msg": "操作成功",
    "data": [
        {
            "id": "1",
            "orderName": "汽车订单",
            "orderPrice": 260000.00,
            "goodId": "3",
            "goodsName": "汽车",
            "goodsPrice": "260000.00",
            "customerId": "e5ce60d54694412b684c37b54b857584",
            "gender": 1,
            "orderStatus": 1,
            "createTime": "2023-06-28 17:51:10",
            "updateTime": "2023-06-29 11:41:14",
            "genderName": "男"
        },
        {
            "id": "2",
            "orderName": "篮球订单",
            "orderPrice": 100.00,
            "goodId": "2",
            "goodsName": "篮球",
            "goodsPrice": "50.00",
            "customerId": "8f33bd0d85cc124c5193c29ae36242a2",
            "gender": 2,
            "orderStatus": 2,
            "createTime": "2023-06-28 17:51:52",
            "updateTime": "2023-06-29 11:41:52",
            "genderName": "女"
        },
        {
            "id": "3",
            "orderName": "书包订单",
            "orderPrice": 20.00,
            "goodId": "1",
            "goodsName": "书包",
            "goodsPrice": "20.00",
            "customerId": "8f33bd0d85cc124c5193c29ae36242a2",
            "gender": 1,
            "orderStatus": 1,
            "createTime": "2023-06-28 17:52:21",
            "updateTime": "2023-06-29 11:41:54",
            "genderName": "男"
        }
    ],
    "success": true
}

# AUTO_TRANS模式使用

存在顾客id,想要自动查询顾客名称和手机号,但是翻译数据源是自定义的形式。

1.创建自定义数据源HosCustomerServiceImpl,添加@AutoTrans注解,指定要翻译的字段、字段别名以及缓存。

@Slf4j
@Service
@AutoTrans(namespace = "customer",fields = {"customerName","phone"},
        defaultAlias = "customer", globalCache = true, cacheSeconds = 10, maxCache = 100)
public class HosCustomerServiceImpl implements AutoTransable<HosCustomer> {

    @Override
    public List<HosCustomer> selectByIds(List<?> ids) {
        log.info("HosCustomerServiceImpl.selectByIds invoke,ids:{}", ids);
        List<HosCustomer> customerList = new ArrayList<>();
        for (Object id : ids) {
            // 编写自定义根据ids获取顾客list的逻辑代码
            HosCustomer hosCustomer = new HosCustomer();
            hosCustomer.setId(String.valueOf(id));
            hosCustomer.setCustomerName("张三");
            hosCustomer.setPhone("13111111111");
            customerList.add(hosCustomer);
        }
        return customerList;
    }

    @Override
    public List<HosCustomer> select() {
        log.info("HosCustomerServiceImpl.select invoke");
        return new ArrayList<>();
    }

    @Override
    public HosCustomer selectById(Object primaryValue) {
        log.info("HosCustomerServiceImpl.selectById invoke,primaryValue:{}", primaryValue);
        // 编写自定义根据id获取顾客的逻辑代码
        HosCustomer hosCustomer = new HosCustomer();
        hosCustomer.setId(String.valueOf(primaryValue));
        hosCustomer.setCustomerName("13222222222");
        hosCustomer.setPhone("李四");
        return hosCustomer;
    }
}

2.实体类HosOrder的字段customerId添加注解@Trans,指定模式为AUTO_TRANS,并设置key与自定义数据源的namespace一致

@Data
@ApiModel(value="HosOrder对象", description="订单表")
@TableName("hos_order")
public class HosOrder implements TransPojo {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "订单名称")
    @TableField("order_name")
    private String orderName;

    @ApiModelProperty(value = "订单总价")
    @TableField("order_price")
    private BigDecimal orderPrice;

    @ApiModelProperty(value = "商品id")
    @TableField("good_id")
    @Trans(type = TransType.SIMPLE, target = HosGoods.class, fields = {"goodsName","goodsPrice"}, refs = {"goodsName","goodsPrice"}) //翻译多个字段
    //@Trans(type = TransType.SIMPLE, target = HosGoods.class, fields = "goodsName", refs = "goodsName") //翻译单个字段
    private String goodId;

    @ApiModelProperty(value = "商品名称")
    @TableField(exist = false)
    private String goodsName;

    @ApiModelProperty(value = "商品单价")
    @TableField(exist = false)
    private String goodsPrice;

    @ApiModelProperty(value = "顾客id")
    @TableField("customer_id")
    @Trans(type = TransType.AUTO_TRANS, key = "customer")
    private String customerId;

    @ApiModelProperty(value = "顾客性别")
    @TableField("gender")
    @Trans(type = TransType.DICTIONARY, key = "gender", fields = "genderName")
    private Integer gender;

    @ApiModelProperty(value = "订单状态")
    @TableField("order_status")
    @Trans(type = TransType.SIMPLE, target = HosOrderStatus.class, fields = "orderStatusDesc", ref = "orderStatusDesc", uniqueField = "orderStatus")
    private Integer orderStatus;

    @ApiModelProperty(value = "订单状态描述")
    @TableField(exist = false)
    private String orderStatusDesc;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

3.HosOrderController添加接口,采用@TransMethodResult进行翻译

@RestController
@RequestMapping("hosOrder")
@Api(tags = "订单表")
public class HosOrderController {

    @Autowired
    private HosOrderService orderService;

    @TransMethodResult
    @GetMapping("/selectOrderList")
    public BaseResponse<List<HosOrder>> selectOrderList() {
        return BaseResponse.success(orderService.list());
    }
}

4.请求接口

url:http://localhost:8007/hosOrder/selectOrderList
RequestMethod:GET

返回结果如下,可以看到genderName也被查询显示出来

{
    "code": "200",
    "msg": "操作成功",
    "data": [
        {
            "id": "1",
            "orderName": "汽车订单",
            "orderPrice": 260000.00,
            "goodId": "3",
            "goodsName": "汽车",
            "goodsPrice": "260000.00",
            "customerId": "e5ce60d54694412b684c37b54b857584",
            "gender": 1,
            "orderStatus": 1,
            "orderStatusDesc": "待支付",
            "createTime": "2023-06-28 17:51:10",
            "updateTime": "2023-06-29 11:41:14",
            "customerPhone": "13111111111",
            "customerCustomerName": "张三",
            "genderName": "男"
        },
        {
            "id": "2",
            "orderName": "篮球订单",
            "orderPrice": 100.00,
            "goodId": "2",
            "goodsName": "篮球",
            "goodsPrice": "50.00",
            "customerId": "8f33bd0d85cc124c5193c29ae36242a2",
            "gender": 2,
            "orderStatus": 2,
            "orderStatusDesc": "待发货",
            "createTime": "2023-06-28 17:51:52",
            "updateTime": "2023-06-29 11:41:52",
            "customerPhone": "13111111111",
            "customerCustomerName": "张三",
            "genderName": "女"
        },
        {
            "id": "3",
            "orderName": "书包订单",
            "orderPrice": 20.00,
            "goodId": "1",
            "goodsName": "书包",
            "goodsPrice": "20.00",
            "customerId": "8f33bd0d85cc124c5193c29ae36242a2",
            "gender": 1,
            "orderStatus": 1,
            "orderStatusDesc": "待支付",
            "createTime": "2023-06-28 17:52:21",
            "updateTime": "2023-06-29 11:41:54",
            "customerPhone": "13111111111",
            "customerCustomerName": "张三",
            "genderName": "男"
        }
    ],
    "success": true
}

可以看到顾客姓名customerCustomerName和手机号customerPhone也被查询出来,同时还在字段前加上了别名customer。查看数据源的打印日志,可以看到执行了自定义数据源的代码。

east-trans-4

# RPC模式使用

存在两个微服务分别为合同服务和用户服务,合同详情中含有唯一键即用户的姓名,现模拟根据用户姓名远程翻译用户手机号。

1.执行下述脚本,创建数据库demo_contract和demo_user,在demo_contract中创建合同表contract,在demo_user中创建用户表staff

CREATE DATABASE demo_contract
CHARACTER SET utf8mb4 
COLLATE utf8mb4_0900_ai_ci;

USE demo_contract;

CREATE TABLE `contract` (
  `id` varchar(32) NOT NULL COMMENT 'ID',
  `name` varchar(32) DEFAULT NULL COMMENT '名称',
  `signer` varchar(32) DEFAULT NULL COMMENT '合同签订人',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT NULL COMMENT '更新时间',
  `is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '是否删除',
  `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户ID',
  `remark` text COMMENT '备注',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='合同表';
insert into `contract` (`id`, `name`, `signer`, `create_time`, `update_time`, `is_deleted`, `tenant_id`, `remark`) values('ab55794e9723defb3f267f5957f0dc7a','汽车订单','丽丽','2023-06-29 18:06:46','2023-06-29 18:06:43','0',NULL,NULL);


CREATE DATABASE demo_user
CHARACTER SET utf8mb4 
COLLATE utf8mb4_0900_ai_ci;

USE demo_user;

CREATE TABLE `staff` (
  `id` varchar(32) NOT NULL COMMENT '主键',
  `name` varchar(500) DEFAULT NULL COMMENT '姓名',
  `gender` varchar(2) DEFAULT NULL COMMENT '性别',
  `age` int DEFAULT NULL COMMENT '年龄',
  `email` varchar(60) DEFAULT NULL COMMENT '邮箱',
  `phone` varchar(500) DEFAULT NULL COMMENT '手机号',
  `tenant_id` varchar(32) DEFAULT NULL COMMENT '租户id',
  `org_id` varchar(32) DEFAULT NULL COMMENT '部门id',
  `description` varchar(255) DEFAULT NULL COMMENT '描述',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  `is_deleted` int DEFAULT NULL,
  `business_key` varchar(64) DEFAULT NULL COMMENT '业务流水号',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='员工信息表'
insert into `staff` (`id`, `name`, `gender`, `age`, `email`, `phone`, `tenant_id`, `org_id`, `description`, `create_time`, `update_time`, `is_deleted`, `business_key`) values('e2ab1960cd737111154d46878b5bccbb','丽丽','女','28','jingjing@qq.com','13201122530','111111',NULL,NULL,'2022-03-09 20:30:51','2023-07-02 10:00:03','0',NULL);

2.参照微服务新建模块示例创建两个微服务,分别为oa-contract-serviceoa-user-service,其中oa-contract-service使用数据库demo_contract,oa-user-service使用数据库demo_user

创建后的服务如下

east-trans-5

合同服务启动类

@MapperScan(basePackages = {"com.mediway.oa.*.mapper"})
@EnableFeignClients
@SpringBootApplication
public class ContractApplication {
    public static void main(String[] args) {
        SpringApplication.run(ContractApplication.class, args);
    }
}

用户服务启动类

@MapperScan(basePackages = {"com.mediway.oa.*.mapper"})
@EnableFeignClients
@SpringBootApplication
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

合同服务数据源

east-trans-6

用户服务数据源

east-trans-7

两个服务同时添加扫描mapper.xml配置

mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml

合同服务设置context-path,用户服务并未设置context-path

server:
  servlet:
    context-path: /contract

3.为合同表和用户表创建相应的entity、service、serviceImpl、mapper、mapper.xml

entity

@TableName(value = "`contract`")
@Data
public class Contract extends BaseEntity {

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "合同名称")
    @TableField(value = "`name`")
    private String name;

    @ApiModelProperty(value = "合同签订者")
    @TableField(value = "`signer`")
    private String signer;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}


@ApiModel("员工信息")
@TableName(value = "staff")
@Data
public class Staff extends BaseEntity {

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "`姓名`", dataType = "`String`", example = "")
    @TableField(value = "`name`")
    private String name;

    @ApiModelProperty(value = "`性别`", dataType = "`String`", example = "")
    @TableField(value = "`gender`")
    private String gender;

    @ApiModelProperty(value = "`年龄`", dataType = "`Integer`", example = "")
    @TableField(value = "`age`")
    private Integer age;

    @ApiModelProperty(value = "`部门id`", dataType = "`String`", example = "")
    @TableField(value = "`org_id`")
    private String orgId;

    @ApiModelProperty(value = "`邮箱`", dataType = "`String`", example = "")
    @TableField(value = "`email`")
    private String email;

    @ApiModelProperty(value = "`手机号`", dataType = "`String`", example = "")
    @TableField(value = "`phone`")
    private String phone;

    @ApiModelProperty(value = "`描述`", dataType = "`String`", example = "")
    @TableField(value = "`description`")
    private String description;

    @ApiModelProperty(value = "是否删除", dataType = "Integer")
    @TableLogic
    @TableField(value = "`is_deleted`")
    private Integer isDeleted;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

service

public interface ContractService extends BaseService<Contract> {

}

public interface StaffService extends BaseService<Staff> {

}

serviceImpl

@Service
public class ContractServiceImpl extends BaseServiceImpl<ContractMapper, Contract> implements ContractService {
    
}

@Service
public class StaffServiceImpl extends BaseServiceImpl<StaffMapper, Staff> implements StaffService {

}

mapper

public interface ContractMapper extends BaseMapper<Contract> {

}

public interface StaffMapper extends BaseMapper<Staff> {
    
}

ContractMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mediway.oa.contract.mapper.ContractMapper">

</mapper>

StaffMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mediway.oa.user.mapper.StaffMapper">
    
</mapper>

4.实体类Contract实现TransPojo接口,在signer字段添加@Trans注解,设置模式为TransType.RPC,指定对方实体类的全类名和serviceName,设置根据唯一键用户姓名去查询对方的手机号。

@TableName(value = "`contract`")
@Data
public class Contract extends BaseEntity implements TransPojo {

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "合同名称")
    @TableField(value = "`name`")
    private String name;

    @ApiModelProperty(value = "合同签订者")
    @TableField(value = "`signer`")
    @Trans(type = TransType.RPC, targetClassName = "com.mediway.oa.user.model.entity.Staff",fields = "phone",ref = "signerPhone", serviceName = "oa-user-service",uniqueField = "name")
    private String signer;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

5.实体类Staff实现TransPojo接口

@ApiModel("员工信息")
@TableName(value = "staff")
@Data
public class Staff extends BaseEntity implements TransPojo {

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "`姓名`", dataType = "`String`", example = "")
    @TableField(value = "`name`")
    private String name;

    @ApiModelProperty(value = "`性别`", dataType = "`String`", example = "")
    @TableField(value = "`gender`")
    private String gender;

    @ApiModelProperty(value = "`年龄`", dataType = "`Integer`", example = "")
    @TableField(value = "`age`")
    private Integer age;

    @ApiModelProperty(value = "`部门id`", dataType = "`String`", example = "")
    @TableField(value = "`org_id`")
    private String orgId;

    @ApiModelProperty(value = "`邮箱`", dataType = "`String`", example = "")
    @TableField(value = "`email`")
    private String email;

    @ApiModelProperty(value = "`手机号`", dataType = "`String`", example = "")
    @TableField(value = "`phone`")
    private String phone;

    @ApiModelProperty(value = "`描述`", dataType = "`String`", example = "")
    @TableField(value = "`description`")
    private String description;

    @ApiModelProperty(value = "是否删除", dataType = "Integer")
    @TableLogic
    @TableField(value = "`is_deleted`")
    private Integer isDeleted;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

6.创建EasyTransRpcContractController

@RestController
@RequestMapping("/easyTransRpcContract")
@Api(value = "合同管理easy-trans-rpc模式控制器")
public class EasyTransRpcContractController {

    @Autowired
    private ContractService contractService;

    @TransMethodResult
    @GetMapping("/selectEasyTransContracts")
    public BaseResponse<List<Contract>> selectEasyTransContracts() {
        return BaseResponse.success(contractService.list());
    }
}

7.分别启动合同服务和用户服务

east-trans-8

east-trans-9

8.请求合同服务接口

url:http://localhost:8007/contract/easyTransRpcContract/selectEasyTransContracts
RequestMethod:GET

返回结果如下,可以看到自动查询到了手机号的值

{
    "code": "200",
    "msg": "操作成功",
    "data": [
        {
            "id": "ab55794e9723defb3f267f5957f0dc7a",
            "createTime": "2023-06-29 18:06:46",
            "updateTime": "2023-06-29 18:06:43",
            "name": "汽车订单",
            "signer": "丽丽",
            "signerPhone": "13201122530",
            "transMap": {}
        }
    ],
    "success": true
}

合同服务的打印日志如下

east-trans-10

用户服务的打印日志如下,可以看到自动查询了用户服务的表数据进行翻译

east-trans-11

# 级联翻译使用

存在生产地城市id,模拟查询出生产地城市名称和生产地省份id、以及级联查询生产地省份名称。

1.HosGoods实体类表新增字段productCityNameproductProvinceIdproductProvinceName,在productCityIdproductProvinceId上添加注解@Trans,并且指定sort,保证先查询的字段序号较小。

@Data
@ApiModel(value="HosGoods对象", description="商品表")
@TableName("hos_goods")
public class HosGoods implements TransPojo {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键", dataType = "String")
    @TableId(value = "id", type = IdType.ASSIGN_UUID)
    private String id;

    @ApiModelProperty(value = "商品名称")
    @TableField("goods_name")
    private String goodsName;

    @ApiModelProperty(value = "商品单价")
    @TableField("goods_price")
    private BigDecimal goodsPrice;

    @ApiModelProperty(value = "生产地城市id")
    @TableField("product_city_id")
    @Trans(type = TransType.SIMPLE, target = HosCity.class, fields = {"name","provinceId"}, refs = {"productCityName","productProvinceId"}, sort = 0)
    private String productCityId;

    @ApiModelProperty(value = "生产地城市名称")
    @TableField(exist = false)
    private String productCityName;

    @ApiModelProperty(value = "生产地省份id")
    @TableField(exist = false)
    @Trans(type = TransType.SIMPLE, target = HosProvince.class, fields = "name", ref = "productProvinceName", sort = 1)
    private String productProvinceId;

    @ApiModelProperty(value = "生产地省份名称")
    @TableField(exist = false)
    private String productProvinceName;

    @ApiModelProperty(value = "创建时间", dataType = "Date")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "修改时间", dataType = "Date")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
}

2.在HosGoodsController中添加接口

@RestController
@RequestMapping("hosGoods")
@Api(tags = "商品表")
public class HosGoodsController {

    @Autowired
    private HosGoodsService goodsService;

    @TransMethodResult
    @GetMapping("/selectHosGoodsById")
    public BaseResponse<HosGoods> selectHosGoodsById (@RequestParam("goodsId") String goodsId) {
        return BaseResponse.success(goodsService.selectById(goodsId));
    }
}

3.请求接口

url:http://localhost:8007/hosGoods/selectHosGoodsById?goodsId=3
RequestMethod:GET

返回结果如下,可以看到首先productCityNameproductProvinceId被自动查询出来,同时productProvinceName也被级联查询出来。

{
    "code": "200",
    "msg": "操作成功",
    "data": {
        "id": "3",
        "goodsName": "汽车",
        "goodsPrice": 260000.00,
        "productCityId": "333",
        "productCityName": "武汉市",
        "productProvinceId": "333333",
        "productProvinceName": "湖北省",
        "createTime": "2023-06-28 17:50:35",
        "updateTime": "2023-06-29 15:35:05"
    },
    "success": true
}

# 反向翻译使用

存在生产地城市名称,模拟反向查询productCityId;存在商品名称和商品单价,模拟反向查询商品id;存在顾客性别名称,模拟反向查询顾客性别类型。

1.创建HosOrderDTO

@Data
@ApiModel(value="HosOrderDTO对象")
public class HosOrderDTO {

    @ApiModelProperty(value = "订单名称")
    private String orderName;

    @ApiModelProperty(value = "生产地城市id")
    // 根据单个字段name查询城市id并赋值给productCityId
    // 拼接后的sql为SELECT name AS groupKey,id as uniqueKey FROM hos_city WHERE name IN (xxx)
    @UnTrans(type= UnTransType.SIMPLE,tableName = "hos_city",refs = "productCityName",columns = "name",uniqueColumn = "id")
    private String productCityId;

    @ApiModelProperty(value = "生产地城市名称")
    private String productCityName;

    @ApiModelProperty(value = "商品id")
    // 根据多个字段goods_name和goods_price查询商品id并赋值给goodId
    // 拼接后的sql为SELECT CONCAT(goods_name,'/',goods_price) AS groupKey,id as uniqueKey FROM hos_goods WHERE CONCAT(goods_name,'/',goods_price) IN (xxx)
    @UnTrans(type= UnTransType.SIMPLE,tableName = "hos_goods",refs = {"goodsName","goodsPrice"},columns = {"goods_name","goods_price"},uniqueColumn = "id")
    private String goodId;

    @ApiModelProperty(value = "商品名称")
    private String goodsName;

    @ApiModelProperty(value = "商品单价")
    private BigDecimal goodsPrice;

    @ApiModelProperty(value = "顾客性别")
    // 根据字典gender的value-genderName查询字典key并赋值给gender
    @UnTrans(type=UnTransType.DICTIONARY,dict="gender",refs = {"genderName"})
    private Integer gender;

    @ApiModelProperty(value = "顾客性别名称")
    private String genderName;
}

2.在HosOrderController中添加接口

@RestController
@RequestMapping("hosOrder")
@Api(tags = "订单表")
public class HosOrderController {
    @Autowired
    private TransService transService;

    @GetMapping("/selectUntransOrder")
    public BaseResponse<HosOrderDTO> selectUntransOrder() {
        HosOrderDTO hosOrderDTO = new HosOrderDTO();
        hosOrderDTO.setOrderName("书包订单");
        hosOrderDTO.setProductCityName("北京市");
        hosOrderDTO.setGoodsName("书包");
        hosOrderDTO.setGoodsPrice(new BigDecimal(20.00).setScale(2));
        hosOrderDTO.setGenderName("男");
        // 手动翻译单个对象
        transService.unTransOne(hosOrderDTO);
        return BaseResponse.success(hosOrderDTO);
    }

    @GetMapping("/selectUntransOrderList")
    public BaseResponse<List<HosOrderDTO>> selectUntransOrderList() {
        List<HosOrderDTO> orderDTOS = new ArrayList<>();
        HosOrderDTO hosOrderDTO1 = new HosOrderDTO();
        hosOrderDTO1.setOrderName("书包订单");
        hosOrderDTO1.setProductCityName("北京市");
        hosOrderDTO1.setGoodsName("书包");
        hosOrderDTO1.setGoodsPrice(new BigDecimal(20.00).setScale(2));
        hosOrderDTO1.setGenderName("男");

        HosOrderDTO hosOrderDTO2 = new HosOrderDTO();
        hosOrderDTO2.setOrderName("篮球订单");
        hosOrderDTO2.setProductCityName("武汉市");
        hosOrderDTO2.setGoodsName("篮球");
        hosOrderDTO2.setGoodsPrice(new BigDecimal(50.00).setScale(2));
        hosOrderDTO2.setGenderName("女");
        orderDTOS.add(hosOrderDTO1);
        orderDTOS.add(hosOrderDTO2);

        // 手动翻译多个对象
        transService.unTransMore(orderDTOS);
        return BaseResponse.success(orderDTOS);
    }
}

3.请求接口

反向翻译单条数据

url:http://localhost:8007/hosOrder/selectUntransOrder
RequestMethod:GET

返回结果如下,可以看到productCityIdgoodIdgender被查询显示出来

{
    "code": "200",
    "msg": "操作成功",
    "data": {
        "orderName": "书包订单",
        "productCityId": "111",
        "productCityName": "北京市",
        "goodId": "1",
        "goodsName": "书包",
        "goodsPrice": 20.00,
        "gender": 1,
        "genderName": "男"
    },
    "success": true
}

反向翻译多条数据

url:http://localhost:8007/hosOrder/selectUntransOrderList
RequestMethod:GET

返回结果如下,可以看到productCityIdgoodIdgender同样被查询显示出来

{
    "code": "200",
    "msg": "操作成功",
    "data": [
        {
            "orderName": "书包订单",
            "productCityId": "111",
            "productCityName": "北京市",
            "goodId": "1",
            "goodsName": "书包",
            "goodsPrice": 20.00,
            "gender": 1,
            "genderName": "男"
        },
        {
            "orderName": "篮球订单",
            "productCityId": "333",
            "productCityName": "武汉市",
            "goodId": "2",
            "goodsName": "篮球",
            "goodsPrice": 50.00,
            "gender": 2,
            "genderName": "女"
        }
    ],
    "success": true
}