Contents
  1. 清明
    1. 支持更复杂的外键关系
    2. 修改高并发下的bug
  2. 阳春
    1. customTypeHandler
  3. 初雪
    1. 自定义主键生成器
    2. 使用或逻辑查询
      1. 普通或逻辑查询
      2. 外键或逻辑查询
    3. 优化使用体验
    4. 全面提升代码质量

清明

对应 flying 版本号为 0.9.9(适用于 mybatis-3.4.x),主要新增特性如下:

支持更复杂的外键关系

在注解 @FieldMapperAnnotation 中加入 类型为 @ForeignAssociation[] 的新属性 associationExtra(),例如为实现 ‘a left join b on (a.f_id = b.id and a.name_a = b.name_b and a.version_a >= b.version_b and …)’,您可以使用如下代码:

1
2
3
@FieldMapperAnnotation(dbFieldName = "f_id", jdbcType = JdbcType.Integer, dbAssociationUniqueKey = "id", associationExtra = {
@ForeignAssociation(dbFieldName = "name_a", dbAssociationFieldName = "name_b"),
@ForeignAssociation(dbFieldName = "version_a", dbAssociationFieldName = "version_b" ,condition=AssociationCondition.GreaterOrEqual) })

同时在默认左外连接的基础上,增加了右外连接,实现方式为在注解 @FieldMapperAnnotation 中加入 新属性 associationType(),例如为实现一个右外连接您可以使用如下代码:

1
@FieldMapperAnnotation(dbFieldName = "f_id", jdbcType = JdbcType.Integer, dbAssociationUniqueKey = "id", associationType = AssociationType.RightJoin)

修改高并发下的bug

修正了在高并发时sql语句会混乱的bug,现在新版本flying一直运行在高并发环境中,完全消除了这个问题

阳春

对应 flying 版本号为 0.9.4(适用于 mybatis-3.4.x),主要新增特性如下:

customTypeHandler

flying-阳春@FieldMapperAnnotation@ConditionMapperAnnotation 增加了 customTypeHandler 属性,使您可以用自定义的 TypeHandler 来处理变量映射,因为 customTypeHandler 具有最高优先级。

初雪

对应 flying 版本号为 0.8.3(适用于 mybatis-3.3.x)和 0.9.3(适用于 mybatis-3.4.x),主要新增特性如下:

自定义主键生成器

为满足个性化主键需要,flying 新增了自定义主键生成器,为此我们在flying:insert语句中新增了括号元素,如下:

1
2
3
flying:insert(uuid)                      使用标准uuid作主键
flying:insert(uuid_no_line) 使用无下横线的uuid作主键
flying:insert(millisecond) 使用毫秒数作主键(需保证每秒并发在1000以下)

当然更多的情况是您会自定义自己的主键生成器,只要您的主键生成器实现了 flying 中的 indi.mybatis.flying.type.KeyHandler 接口即可,比如这样调用一个自定义的主键生成器类:

1
flying:insert(indi.mybatis.flying.handlers.MySnowFlakeKeyHandler)

(上面的 indi.mybatis.flying.handlers.MySnowFlakeKeyHandler 是一个雪花主键生成器的 java 版本实现。雪花主键生成器由 tweeter 发明用于处理大规模并行写入,主键采用 float 类型存储以节省资源,自带递增无需 order by,单台主机每秒可产生 400 万个不同主键,最多可 1024 台主机集群同时工作。flying 中提供了一个实现方式,代码见此

在某些特殊业务场景中,您需要使用主键表达一定的业务含义,这时自定义主键生成器会显得非常有效。

这里有一个使用了自定义主键生成器的例子,相信您看完以后会对此特性了然于胸。

使用或逻辑查询

普通或逻辑查询

“或”逻辑查询是 初雪 版本新增的最重要内容。为了实现此特性 flying 新增了 Or 标签类(代码见此),这个标签的内容是ConditionMapperAnnotation标签的数组,所以在查询条件类中可以有如下标签代码:

1
2
3
4
5
@Or({
@ConditionMapperAnnotation(dbFieldName = "name", conditionType = ConditionType.HeadLike),
@ConditionMapperAnnotation(dbFieldName = "age", conditionType = ConditionType.Equal),
@ConditionMapperAnnotation(dbFieldName = "name", conditionType = ConditionType.HeadLike)
})

(上面是实现 name like ‘XXX%’ or age = ‘YYY’ or name like ‘ZZZ%’ 查询的条件)

同时为了赋值方便,我们采用Object数组的不定参数形式作为变量类型,于是整个代码变成了:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Or({
@ConditionMapperAnnotation(dbFieldName = "name", conditionType = ConditionType.HeadLike),
@ConditionMapperAnnotation(dbFieldName = "age", conditionType = ConditionType.Equal),
@ConditionMapperAnnotation(dbFieldName = "name", conditionType = ConditionType.HeadLike)
})
private Object[] condition1;

public Object[] getCondition1 () {
return condition1;
}
public void setCondition1 (Object... condition1) {
this. condition1 = condition1;
}

如果我们描述 “name like ‘张%’ or age = 27 or name like ‘李%’ “,代码如下:

1
2
personCondition.setCondition1("张", 27, "李");
/* 注意参数顺序和 condition1 上 @ConditionMapperOrAnnotation 的内部顺序一致 */

您之前掌握的绝大部分 ConditionMapperAnnotation 都可以写在 @Or 中,只有本身就是集合型的条件类型例外,以下列出不能进入 @Or 的类型:

MultiLikeANDMultiLikeORInNotIn

除此之外的查询条件均可以参与或查询。

外键或逻辑查询

flying 在同库跨表查询时也可以做不同表上条件的或逻辑查询,比如我们要实现 person.name = ‘XXX’ or role.name = ‘YYY’ 查询,其中 role 是 person 业务上的父对象。我们可以在 role 的条件类中加入如下变量:

1
2
3
4
5
6
7
8
9
10
11
@Or({ 
@ConditionMapperAnnotation(dbFieldName = "name", conditionType = ConditionType.Equal),
@ConditionMapperAnnotation(dbFieldName = "name", conditionType = ConditionType.Equal, subTarget = mypackage.Person.class) })
private Object[] roleNameEqualsOrPersonNameEquals;

public Object[] getRoleNameEqualsOrPersonNameEquals () {
return roleNameEqualsOrPersonNameEquals;
}
public void setRoleNameEqualsOrPersonNameEquals (Object... roleNameEqualsOrPersonNameEquals) {
this. roleNameEqualsOrPersonNameEquals = roleNameEqualsOrPersonNameEquals;
}

上面的代码中第一行 ConditionMapperAnnotation 指的是 role 表,第二行指的是 person 表,因为是由 role 指向 person,所以第二行出现了 subTarget 参数用来引导路径,它的值就是业务上子对象的类路径。

值得注意的是,外键或逻辑查询中,跨表的 @Or 条件永远要写在业务上的父对象里,这是考虑到从子对象上寻找父对象并非唯一(例如多重外键情况,一个 person 有多个 role 型父对象,分别表示主要角色和次要角色等),然而从父对象上寻找子对象永远是唯一的。

如果您要查询用户名为“张三”或角色名为“wfadmin”的用户时,您只需这样做:

1
2
3
4
5
RoleConditon rc = new RoleCondition();
rc.setRoleNameEqualsOrPersonNameEquals("wfadmin","张三");
Person p = new Person();
p.setRole(rc);
Person<Collection> persons = personService.selectAll(p);

无论 role 是 person 业务上的直接父对象还是间接父对象都可以这样查询。

优化使用体验

@QueryMapperAnnotation 现在可以省略,只要您的某个类既继承实体 pojo 又实现 Conditionable 接口 flying 就可以判断出它是相关 pojo 的条件类。当然这个标签出现在代码里也没有任何问题。

全面提升代码质量

初雪 中,我们把代码质量作为提升的重要一环,同时使用 阿里 P3C 和 SonarQube 来修正代码缺陷,当您阅读 flying 源码时您会深切感受到这一点。

Contents
  1. 清明
    1. 支持更复杂的外键关系
    2. 修改高并发下的bug
  2. 阳春
    1. customTypeHandler
  3. 初雪
    1. 自定义主键生成器
    2. 使用或逻辑查询
      1. 普通或逻辑查询
      2. 外键或逻辑查询
    3. 优化使用体验
    4. 全面提升代码质量