# 实体定义
实体可以认为是对数据库表的映射,实体的字段即为列的映射,有了这一份数据,可以通过调用简单的方法快速进行数据访问、生成SQL,可以控制字段级别的可操作性,甚至快速生成对应的CRUD接口等。
实体常用可见:
在实体生效范围内,创建Class类并使用@Entity注解定义实体,实体名默认为类名(若类名以Entity结尾,则以去掉Entity后缀作为实体名),映射的数据库表名默认为实体名驼峰转下划线格式,且首字母小写:
import fly.core.data.annotation.Entity;
// 默认实体名:FlyUser,默认映射数据库表名:fly_user
@Entity
public class FlyUserEntity {}
# @Entity
@Entity为定义实体的注解,可配置属性如下:
| 注解属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
name | 实体名称 | String | 类名,默认移除Entity后缀 |
table | 数据库表名 | String | 实体名驼峰转下划线格式,首字母小写 |
sortable | 可排序的字段列表 | String[] | - |
filterable | 可过滤的字段列表 | String[] | - |
searchable | 可搜索字段,使用参考快速搜索 | String[] | - |
writable | 可写的字段列表,即在创建、修改操作中是否允许外部传入字段值 | String[] | - |
autoDdl | 是否自动建表,自动补充字段及关系外键等,见数据库管理 | AutoDdl | AutoDdl.SUPPORTED |
autoDdlProperty | 是否自动建表的配置属性。使用:@Entity(autoDdlProperty = "${auto-ddl-property}"),然后通过Spring或环境变量等方式配置auto-ddl-property: DISABLED | String | - |
indexes | 使用参考定义索引 | Index[] | - |
keys | 使用参考唯一键 | Key[] | - |
foreignKeys | 使用参考定义外键 | ForeignKey[] | - |
listeners | 监听使用Dao进行实体新增/更新等操作,使用参考监听器 | Class<?>[] | - |
# 定义字段
字段在实体中,可以作为对数据库表的列的映射。
字段命名规则:类属性要作为字段时,建议使用驼峰命名,默认字段名为属性名,字段对应的数据库列名默认为字段名驼峰转下划线格式,且首字母小写。
# 主键字段
主键一般为自动生成,框架根据常见场景提供了几个不同生成策略的主键字段注解:
| 注解 | 生成策略 | 类型参考 |
|---|---|---|
@AutoIncrement | 数据库自增 | Integer |
@UUID | 生成长度为36的随机字符串 | String |
@ShortUUID | 生成长度为22的随机字符串 | String |
@SnowflakeID | 生成18位的数值 | Long |
@Entity
public class FlyUserEntity {
@UUID
protected String id;
// get/set
}
若不需要自动生成,可以使用无生成策略的主键字段注解@Id,@Id可配置属性如下:
| 注解属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
generator | Id生成策略,相当于在属性上添加@Generator注解。设置为none表示不需要自动生成Id | String | auto,根据属性类型自动处理 |
# 普通字段
对于主键外的普通列,可使用@Column或者@NullColumn注解定义字段。@Column注解默认字段不可为空,@NullColumn注解认为字段可为空,@Column中可以通过nullable属性修改字段是否为空的状态。
@Column
protected String name;
@Column(nullable = true)
protected String title;
@NullColumn(name = "description")
protected String desc;
@Column字段注解可配置属性综合如下(@NullColumn相似,只是部分默认值有所不同):
| 注解属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
name | 数据库列名 | String | 字段名下划线格式 |
domain | 指定字段定义域名称 | String | - |
definition | 等同于注解value(),字段定义表达式,可以定义数据库列类型等 | String | - |
unique | 是否唯一,用于ddlAuto(数据库管理) | boolean | false |
nullable | 是否允许为null | boolean | false |
length | 数据库列长度 | int | - |
precision | 数据库列数值精度 | int | - |
scale | 数据库列数值范围 | int | - |
columnDefault | @ColumnDefault - 字段在数据库中的默认值,用于ddlAuto(数据库管理) | String | - |
expression | @ValueExpression - 创建和更新时字段的求值表达式 | String | - |
defaultExpression | @DefaultExpression - 创建时若未传入字段值,执行该表达式取默认值 | String | - |
insertExpression | 创建时字段的求值表达式 | String | - |
updateExpression | 更新时时字段的求值表达式 | String | - |
insertable | 是否允许在创建时写入数据库 | boolean | true |
updatable | 是否允许在更新时写入数据库 | boolean | true |
settable | @Settable - 是否允许由外部赋值 | boolean | - |
onInsertNotSettable | 当插入记录时发现不可赋值字段时的处理方式:DENY为拒绝赋值并抛出异常;IGNORE为忽略字段 | OnNotSettable | DENY |
onUpdateNotSettable | 当更新记录时发现不可赋值字段时的处理方式 | OnNotSettable | DENY |
writeProtected | 是否开启写保护,写保护字段不能直接写入,需要在dao创建或更新时执行额外的方法:dao.withProtected().update(entity) | boolean | false |
sortable | @Sortable - 是否允许排序 | boolean | false |
searchable | @Searchable - 是否作为快捷搜索字段 | boolean | false |
filterable | @Filterable - 是否允许过滤 | boolean | false |
filteredByDefault | 是否在查询中默认作为过滤条件 | boolean | false |
filteredExpression | 默认过滤条件的求值表达式,表达式结果作为字段过滤条件,与filteredByDefault、filteredIf组合使用 | String | - |
filteredIf | 表达式,在filteredByDefault的基础上再次动态判断是否过滤filteredExpression | String | - |
部分属性有同名独立注解,独立注解内部也能够设置字段的其他属性,如@ValueExpression(settable = true),若一个类属性上有多个注解,且都设置了同一个字段属性:
@Column(writable = false)
@ValueExpression(settable = true)
protected String appId;
一般只有与注解的默认值不同时才会将值设置入字段(自定义注解除外,如常用注解),再此基础上根据基础注解处理的优先级从低到高为:
@Column/@NullColumn- 类似
@Writable的独立注解
大部分情况下,字段的属性配置优先级可以参考如上。
# 定义表达式
表达式解析类:
fly.data.relational.domain.DomainParser
varchar(200) not null default 'test'
一个表达式可以同时定义字段名、数据类型或其他属性,不同属性由空格分隔,部分特殊配置可能会跨空格解析。
- 列类型
varchar(200)
支持类型可见fly.data.common.jdbc.JdbcTypeMapping.getTypeCode(String typeName)方法,不区分大小写,类型后若带括号,只有一个数值则为长度type(length),有两个数值则为精度及范围type(precision,scale)。
常用类型有:
varchar、data、time、timestamp、boolean、longvarchar、int、long。
- 匹配格式:
{property}({value})
{property}来源于fly.data.relational.domain.DomainBuilder,如DomainBuilder内有属性String expr,则:
'expr(#vars.now)' -> @Column(expr = "#vars.now")
对于Boolean类型的属性,若要设为true,也可以简写为:
'expr(#vars.now) writable' -> @Column(expr = "#vars.now", writable = true)
- 特殊配置
| 配置 | 说明 |
|---|---|
auto_increment / increment | 数据库自增 |
primary / primary key | 是否为主键 |
optional / null / not null / required | 影响nullable,是否可为null |
default {value} | 数据库列默认值 |
# 定义域
了解字段表达式后,对于一些通用的字段配置可以抽出作为一个定义域,在@Column(domain = "name")中使用,方便统一管理。在YAML格式的配置文件中进行定义,文件读取优先级从低到高为:
classpath*:META-INF/domains/*.ymlclasspath*:META-INF/domains.ymlclasspath:domains/*.ymlclasspath:domains.yml
示例:
/resources/domains.yml
json1: varchar(200) null default '{}'
@Column(domain = "json1", length = "500")
protected String json;
domain指定定义域,json字段根据名称获取对应的字段配置,这里注解配置的优先级会高于定义域(需与注解默认值不同才会生效),如果需要自定义部分配置可以直接在注解中调整。
# 常用注解
框架提供常用使用场景的字段注解,下列说明是指配置注解后默认生效的状态,注解内部可以对部分字段属性做修改,具体可进注解内查看。
注解包路径为:
fly.core.data.domains
| 字段注解 | 默认作用 |
|---|---|
@CreatedAt | 表示创建时间字段,创建时自动填充系统当前时间,设置后字段不可修改,忽略外部传值 |
@CreatedBy | 表示创建人字段,创建时自动填充当前用户id,设置后字段不可修改,忽略外部传值 |
@CreatedByName | 表示创建人名称字段,创建时自动填充当前用户name,设置后字段不可修改,忽略外部传值 |
@CreatedFrom | 表示从哪个客户端创建,创建时自动填充当前客户端id,设置后字段不可修改,忽略外部传值 |
@Deleted | 表示软删除字段,默认0未删除、1已删除,设置后字段不可外部传值 |
@Password | 表示密码字段,指定序列化器为password,长度默认200 |
@TenantId | 表示租户字段,创建时自动填充当前用户或客户端的租户id,设置后字段不可修改 |
@UpdatedAt | 表示更新时间字段,更新时自动填充系统当前时间,忽略外部传值 |
@UpdatedBy | 表示更新人字段,更新时自动填充当前用户id,忽略外部传值 |
@UpdatedByName | 表示更新人字段,更新时自动填充当前用户name,忽略外部传值 |
@CreatedBy
protected String createdBy;
# 定义索引
在@Entity注解的indexes属性或者直接在实体类上使用@Index注解进行索引定义:
@Entity(
indexes = {
@Index(name = "idx_login_name", columns = "loginName", unique = false)
}
)
public class UserEntity {
@Id
protected String id;
@Column
protected String loginName;
// get/set
}
示例中idx_login_name为索引名称,columns为索引包括的字段,unique表示该索引是否为唯一索引。
定义索引可以用于在数据迁移的ddlAuto自动构建数据库表中自动创建索引。
# 唯一键
在@Entity注解的keys属性或者直接在实体类上使用@Key注解进行唯一键定义:
@Entity(
keys = {
@Key(name = "ak_auth_code", fields = {"authorId", "code"})
}
)
public class Entity {
@Id
private String id;
@Column
@ManyToOne(Author.class)
private String authorId;
@Column
private String code;
// get/set
}
唯一键可以在数据访问的修改/删除/查询方法中起到类似主键ID的作用,同时在数据迁移的ddlAuto自动构建数据库表中自动创建唯一索引。
# 定义外键
在@Entity注解的foreignKeys属性或者直接在实体类上使用@ForeignKey注解进行外键定义:
@Entity(
foreignKeys = {
@ForeignKey(name = "fk_org_parent", columns = "parentId", foreignEntity = Org.class, foreignColumns = "id")
}
)
public class Org {
@Id
protected String id;
@Column
protected String name;
@NullColumn("varchar(36)")
protected String parentId;
// get/set
}
示例中外键名称为fk_org_parent,columns与foreignColumns为外键对应的字段,严格按照顺序对应,foreignEntity为外键关联的实体类。
用于在数据迁移的ddlAuto自动构建数据库表中自动创建外键约束。
# 数据模型
数据模型相当于实体的拓展,根据增、改、查询等场景,一个实体可以有多个数据模型,不同数据模型拥有的属性可能不同,又可以共享实体及实体中同名属性的字段定义。
使用@MappingToEntity注解的value或name属性指定映射的实体,注意,数据模型必须有有效的映射实体,没有将抛出异常。
@MappingToEntity(Entity.class)
public class EntityCreateParams {}
| 注解属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
value | 映射的实体类,优先根据value查找实体 | Class<?> | Void.class |
name | 映射的实体名,若value不是有效值(等于Void.class或为当前类),才根据name查找实体 | String | - |