字段
@Field
/** * 模型字段注解,未注解的字段不会被当做模型字段,而会被直接忽略 */public @interface Field { /** * 字段显示名称,用于前端界面展示 */ String name() default "";
/** * 字段描述 */ String desc() default "";
/** * ❗️字段类型 * ❗️默认为根据字段 Java 类型或 Meta 信息注解自动推断; * ❗️部分字段类型无法推断,需要显示声明 * * @see FieldType */ FieldType type() default FieldType.Inference;
/** * 是否可空 */ boolean nullable() default true;
/** * 默认值 */ String defaultValue() default "";}Meta Annotation
Meta Annotation 用于为特定字段类型声明补充信息,例如字符串长度限制、数字精度、附件允许格式等,建议使用IDEA插件支持创建字段,支持并提示所有Meta Annotation。
@TextMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface TextMeta { int DEFAULT_LENGTH = 256;
/** * 字符串长度 */ int length() default DEFAULT_LENGTH;
/** * 仅对 Text 类型字段有效 * STRING(Test)+TIMES(yyyy-MM-dd HH:mm:ss.SSS)+INCRE(1,4,0,100)+RANDOM(4,1) * * @see <a href="https://yuque.antfin.com/docs/share/65baa6b9-d03a-41b7-98d4-68a8a76ba2cb#85a838f4">规则字段文档</a> */ String rule() default "";}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Text | java.lang.String |
| FieldType.MultiText | Collection<java.lang.String> |
| FieldType.RichText | java.lang.String |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| length | Int | 256 | 字符串长度 |
| rule | String | / | Text 类型规则字段,详细请查看规则字段定义 |
@IntMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface IntMeta {
/** * 默认整数位数 */ int DEFAULT_DIGITS = 7;
/** * 整数位数 */ int digits() default DEFAULT_DIGITS;
/** * 数值展示的单位,例如 % 、天等等 */ String unit() default "";
/** * 格式化表达式 */ String format() default "";}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Int | java.lang.Integer java.lang.Long java.lang.Short java.math.BigInteger |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| digits | Int | 7 | 整数位数 |
| unit | String | / | 数值展示的单位,例如 % 、天等等 |
| format | String | / | 格式化表达式 |
@FloatMeta
❗️百分比类型使用 @PercentMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface FloatMeta {
/** * 默认整数位数 */ int DEFAULT_INT_DIGITS = 7;
int DEFAULT_DECIMAL_DIGITS = 2;
int DEFAULT_DISPLAY_DIGITS = 2;
/** * 整数位数 */ int intDigits() default DEFAULT_INT_DIGITS;
/** * 小数位数 */ int decimalDigits() default DEFAULT_DECIMAL_DIGITS;
/** * 百分比展示 */ boolean percentage() default false;
/** * 百分比展示小数位数 */ int displayDigits() default DEFAULT_DISPLAY_DIGITS;
/** * 数值展示的单位,例如 % 、天等等 */ String unit() default "";
/** * 格式化表达式 */ String format() default "";}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Float | java.lang.Float java.lang.Double java.math.BigDecimal |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| intDigits | Int | 7 | 整数位数 |
| decimalDigits | Int | 2 | 小数位数 |
| percentage | Boolean | false | 百分比展示 |
| displayDigits | Int | 2 | 百分比展示小数位数 |
| unit | String | / | 数值展示的单位,例如 % 、天等等 |
| format | String | / | 格式化表达式 |
@PercentMeta
/** * 百分比类型, 前端会自动根据比率类型来展示 */@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface PercentMeta {
/** * 整数位默认位数 */ int DEFAULT_INT_DIGITS = 26;
/** * 小数位默认位数 */ int DEFAULT_DECIMAL_DIGITS = 6;
/** * 小数位默认展示位数 */ int DEFAULT_DISPLAY_DECIMAL_DIGITS = 2;
/** * 整数位数 */ int intDigits() default DEFAULT_INT_DIGITS;
/** * 小数位数 */ int decimalDigits() default DEFAULT_DECIMAL_DIGITS;
/** * 展示小数位数 */ int displayDecimalDigits() default DEFAULT_DISPLAY_DECIMAL_DIGITS;}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Percent | java.lang.Float java.lang.Double java.math.BigDecimal |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| intDigits | Int | 26 | 整数位数 |
| decimalDigits | Int | 6 | 存储的小数位数 |
| displayDecimalDigits | Int | 2 | 前端展示的小数位数 |
@CurrencyMeta - Currency
金额类型
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface CurrencyMeta {
/** * 默认整数位数 */ int DEFAULT_INT_DIGITS = 26;
int DEFAULT_DECIMAL_DIGITS = 6;
/** * 整数位数 */ int intDigits() default DEFAULT_INT_DIGITS;
/** * 小数位数 */ int decimalDigits() default DEFAULT_DECIMAL_DIGITS;}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Currency | io.terminus.trantorframework.api.type.Currency |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| intDigits | Int | 26 | 整数位数 |
| decimalDigits | Int | 6 | 小数位数 |
金额类型字段使用说明 金额字段和其他类型字段的核心区别在于金额字段为复合字段,金额字段在数据库中存储为两个字段type和value,金额字段的CURD操作和其他类型的字段有一些区别,假设存在如下模型定义
@Model(name = "报价单")public class PricingBO extends BaseModel<Long> {
@Field(name = "金额", nullable = true) @CurrencyMeta(intDigits = 26, decimalDigits = 6) private Currency amount;}金额字段插入
insert into pay_PricingBO (amount) values ('{\"type\":\"CNY\", \"value\":100}');金额字段更新
全量更新
update pay_PricingBO set amount = '{\"type\":\"CNY\", \"value\":200}';计算更新
update pay_PricingBO set amount = amount + 200;不支持的更新
update pay_PricingBO set amount = 200; --不支持金额字段查询
金额字段查询,只支持以value值为条件查询
select * from pay_PricingBO where amount = 200;不支持以type为条件查询
select * from pay_PricingBO where amount = 'CNY'; --不支持金额字段删除 目前不支持以金额字段为条件删除数据
delete from meta_store_Total where `totalAmt` = 1; --不支持delete from meta_store_Total where `totalAmt` = 'CNY'; --不支持@BooleanMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface BooleanMeta { /** * 当值为 true 时的前端显示标签 */ Label trueLabel() default @Label("是");
/** * 当值为 false 时的前端显示标签 */ Label falseLabel() default @Label("否");}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Boolean | java.lang.Boolean |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| trueLabel | String | 是 | 当值为 true 时的前端显示标签 |
| falseLabel | String | 否 | 当值为 false 时的前端显示标签 |
@DictionaryMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface DictionaryMeta { /** * 字典值来源类,不同字典值的展示信息通过在字典类中的值上注解 {@link Label} 来实现 */ Class<?> value() default Object.class;}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Dictionary | java.lang.String java.lang.Integer |
| FieldType.MultiDictionary | Collection<?> |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| clazz | Class | / | 字典值来源类,不同字典值的展示信息通过在字典类中的值上注解 @Label 来实现 |
| dictionaryType | TDictType | TDictType.String | 字典类型 |
@DateTimeMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface DateTimeMeta { /** * 时间的最小单位,例如 小时、分钟等等 */ TimeUnit unit() default TimeUnit.MINUTES;
/** * 格式化表达式,用于前端展示格式所用。 * 需要注意这里目前使用的并不是 Java 的 SimpleDateFormat 的格式,而是前端采用的 moment 的 format 格式。 * 参考 https://momentjs.com/ */ String format() default "";}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.DateTime | java.time.LocalDateTime java.util.Date |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| unit | TimeUnit | TimeUnit.MINUTES | 字典值来源类,不同字典值的展示信息通过在字典类中的值上注解 @Label 来实现 |
| format | String | / | 格式化表达式,用于前端展示格式所用。 需要注意这里目前使用的并不是 Java 的 SimpleDateFormat 的格式,而是前端采用的 moment 的 format 格式。 参考 https://momentjs.com/ |
@TimeMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface TimeMeta { /** * 时间的最小单位,例如 小时、分钟等等 */ TimeUnit unit() default TimeUnit.MINUTES;
/** * 格式化表达式 */ String format() default "";}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Time | java.time.LocalTime java.util.Date |
属性说明表
同 @DateTimeMeta
@ImageMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface ImageMeta { /** * 文件最大允许大小,单位 KB ,默认 Integer.MAX_VALUE ,大约 2T */ int maxSize() default Integer.MAX_VALUE;
/** * 附件的读取策略, 默认为私有读 */ ReadPolicy readPolicy() default ReadPolicy.PRIVATE;}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Image | java.lang.String |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| maxSize | int | Integer.MAX_VALUE | 文件最大允许大小,单位 KB ,默认 Integer.MAX_VALUE ,大约 2T |
| readPolicy | ReadPolicy | / | 附件的读取策略, 默认为私有读 |
@AttachmentMeta
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface AttachmentMeta { enum ShowType { PICTURE, AVATAR, VIDEO, DOCUMENT, ALL }
/** * 展示类型, 默认不限制 */ ShowType showType() default ShowType.ALL;
/** * 允许的文件类型,后缀名,不区分大小写,留空则为不限制,默认不限制 * 可以使用内置常量来简化常见文件类型的声明 * * @see AllowedTypes */ String[] allowedTypes() default {};
/** * 单文件最大允许大小,单位 KB ,默认 Integer.MAX_VALUE ,大约 2T */ int maxSize() default Integer.MAX_VALUE;
/** * 允许上传文件数量,默认 1 */ int countLimit() default 1;
/** * 附件的读取策略, 默认为私有读 */ ReadPolicy readPolicy() default ReadPolicy.PRIVATE;}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Attachment | io.terminus.trantorframework.api.type.Attachment |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| showType | ShowType | ShowType.ALL | 展示类型, 默认不限制 |
| allowedTypes | String[] | {} | 允许的文件类型,后缀名,不区分大小写,留空则为不限制,默认不限制 。 |
| maxSize | int | Integer.MAX_VALUE | 单文件最大允许大小,单位 KB ,默认 Integer.MAX_VALUE ,大约 2T |
| countLimit | int | 1 | 允许上传文件数量 |
| readPolicy | ReadPolicy | ReadPolicy.PRIVATE | 附件的读取策略, 默认为私有读 |
@LinkMeta
声明模型的 ToOne 关联关系,会自动根据被声明字段的类型是否是 Collection 推断出是 LinkOne 还是 LinkMany,前往了解更多。
/** * 在两个模型之间声明一个 Link 关系 */@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface LinkMeta {}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.Link | Class<? extends RootModel> |
| FieldType.LinkMany | Collection<Class<? extends RootModel>> |
@LookupMeta
声明关联模型的反查字段,前往了解更多。
/** * 例如 在 A 模型上有一个 a 的 link 字段,关联到 B 模型,那么在 B 模型中, * 我们可以写一个 b 字段,同时加上 {@code @LookupMeta( field = "a" )},这样就实现了通过 b 反向查询 A * <p> * 如果需要申明多对多关系,可以配合 {@link JunctionMeta} 使用 */@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface LookupMeta { /** * 对应模型的 Link 字段名 */ String linkField() default "";}类型对照表
| Trantor 类型 | Java 类型 |
|---|---|
| FieldType.LookupOne | Class<? extends RootModel> |
| FieldType.LookupMany | Collection<Class<? extends RootModel>> |
属性说明表
| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| linkField | String | / | 对应模型的 Link 字段名 |
@JunctionMeta
声明多对多关联关系(ManyToMany)的两个模型对象间的中间对象/连接点,前往了解更多。
@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface JunctionMeta { /** * 多对多中间模型 */ Class<? extends RootModel<?>> model();
/** * 中间模型里对应的 Lookup 字段 */ String lookupField() default "";}| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| model | 模型类 Class | / | 声明多对多的两个模型的中间模型 |
| lookupField | String | / | 中间模型里对应当前的 Lookup 字段 |
@Transient
标记一个字段为非持久化字段,即字段数据不会保存到数据库中,仅在持久化模型字段上标记生效。
@Model(name = "员工")public class Staff extends BaseModel<Long> {
@Field(name = "出生日期", type = FieldType.Date) private Date birthday;
// 非持久化字段,年龄通过 birthday 实时计算 @Transient @Field(name = "年龄") private Integer age;}@Reference
冗余字段注解,可以在模型中冗余关联模型的字段。只能冗余 link 关系模型中的字段。
/** * 冗余字段 只能关联 link 字段 * 默认同步策略为 NEVER ,即只在该条记录创建时填充一次冗余字段 * <p> * 如果希望总是获得最新的数据,可将同步策略改为 SYNC ,但使用 SYNC 需要特别小心,可能导致很大数据量的冗余字段更新 */@Documented@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Reference { /** * 关联的 ToOne 字段名 */ String fromField();
/** * 关联到的模型内字段名 */ String mappingField();
/** * 数据同步策略 */ Refresh onChange() default Refresh.NEVER;
enum Refresh { NEVER, SYNC, ASYNC }}| AtrributeName | Type | Default | Explain |
|---|---|---|---|
| fromField | String | / | 关联的 ToOne 字段名 |
| mappingField | String | / | 关联到的模型内字段名 |
| onChange | Refresh | Refresh.NEVER | 数据同步策略,默认同步策略为 NEVER ,即只在该条记录创建时填充一次冗余字段。 如果希望总是获得最新的数据,可将同步策略改为 SYNC ,但使用 SYNC 需要特别小心,可能导致很大数据量的冗余字段更新 。 |
可设置冗余字段的字段类型:
- Text
- MultiText
- RichText
- Int
- Boolean
- Image
举例:
@Field(name = "地址")@LinkMetaprivate Address singleAddress;
@Field(name = "省")@Reference( fromField = User.singleAddress_field, mappingField = Address.province_field)private String province;@FieldTemplate
描述性字段,可定义在任何类型模型的任何字段上,视图渲染效果仅针对Form和Detail有效,模版内容支持国际化(交付控制台|配置|国际化|翻译|模型|字段元信息翻译)
/** * 描述性字段渲染模版 * 带 @{fieldName} 的字符串模版,fieldName为当前@SettingFieldMeta所在字段的字段名 * eg: "提交订单后分钟后@{fieldName}未支付,自动取消订单" * <p> */@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface FieldTemplate { String value() default "";}示例:
@SettingModel( name = "订单配置")public class MySettingModel extends BaseSettingModel { @Field(name = "自动审核时间") @FieldTemplate("订单审核@{" + autoReviewTime_field + "} 分钟后,系统进行自动配货。") private Long autoReviewTime;}视图渲染效果:
订单审核 . . 钟后,系统进行自动配货。
@Encrypted
在数据库中,有些关键数据敏感度比较高,需要加密存储,即使数据库泄露也能保证一定的安全性。因此,DS 提供了数据加密功能,使关键的数据保存时经过 DS 加密存储,通过 DS 查询加密数据时,DS 先解密被加解密的数据,然后在返回给用户(业务模块),因此,DS 的数据加密功能对用户来说是无感知的。
@Model(name = "员工")public class Staff extends BaseModel<Long> {
@Field(name = "Item name") private String name;
@Encrypted @Field(name = "工资") private String salary;}更多有关加密字段的介绍请查看 DS加密字段用户指南
模型字段类型推断
对于字段类型,Trantor 提供了一种 类型推断 的机制,即在未定义字段类型 @Field(type=...) 的前提下,Trantor 会根据当前字段的 Java 类型以及 Meta-Annotation 声明信息主动推断模型字段所属类型,
JSR-303 Annotation
除了上述的一些 Meta-Annotation 外,Trantor 还支持在模型字段上声明一部分 JSR-303 注解,用于对字段仅在前端视图上进行规则校验,并且这些规则不会在数据库层面体现。
| Annotation | 全限定名 | 支持的字段类型 | 作用 |
|---|---|---|---|
| @NotNull | javax.validation.constraints.NotNull | 全部 | 可以定义在模型字段上,与 @Field(nullable = false) 不同, @Field(nullable = false) 体现在数据库 DDL 上,从数据库层面限制数据列必填,而 @NotNull 的作用是在前端视图上进行对字段进行非空校验。 |
| @Pattern | javax.validation.constraints.Pattern | 全部 | 正则表达式校验字段值 |
| @Max | javax.validation.constraints.Max | 数值类型: FieldType.Int FieldType.Float FieldType.Percent | 数值最大值校验 |
| @Min | javax.validation.constraints.Min | 数值类型: FieldType.Int FieldType.Float FieldType.Percent | 数值最小值校验 |
| @Size | javax.validation.constraints.Size | 文本类型: FieldType.Text FieldType.MultiText FieldType.RichText FieldType.Dictionary FieldType.Image FieldType.Password FieldType.Email FieldType.Phone | 文本最大字符长度校验 |
模型间关系
Trantor 通过在模型上定义关联关系字段来描述模型间关系,支持所有 OneToOne 、OneToMany 、ManyToOne 和 ManyToMany 四种关系,详情请查看link-relationship