feat: 实现多对多查询

This commit is contained in:
wangyu 2024-06-29 13:50:37 +08:00
parent e448280290
commit 89eaae41d5
17 changed files with 169 additions and 28 deletions

View File

@ -23,8 +23,9 @@
<artifactId>flyfish-common</artifactId> <artifactId>flyfish-common</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>com.flyfish.framework</groupId>
<artifactId>spring-data-relational</artifactId> <artifactId>flyfish-data-r2dbc</artifactId>
<version>${revision}</version>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -3,6 +3,7 @@ package com.flyfish.framework.domain.po;
import com.flyfish.framework.domain.tree.TreeDomain; import com.flyfish.framework.domain.tree.TreeDomain;
import lombok.*; import lombok.*;
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.relational.core.mapping.Table;
/** /**
@ -24,6 +25,7 @@ public class Department extends TreeDomain<Department> {
/** /**
* 部门的完整名称 * 部门的完整名称
*/ */
@Column("full_name")
private String fullName; private String fullName;
/** /**

View File

@ -3,8 +3,9 @@ package com.flyfish.framework.domain.po;
import com.flyfish.framework.domain.base.AuditDomain; import com.flyfish.framework.domain.base.AuditDomain;
import com.flyfish.framework.enums.NamedEnum; import com.flyfish.framework.enums.NamedEnum;
import com.flyfish.framework.enums.RoleType; import com.flyfish.framework.enums.RoleType;
import com.flyfish.framework.r2dbc.mapping.Association;
import lombok.*; import lombok.*;
import org.springframework.data.annotation.Reference; import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.relational.core.mapping.Table;
@ -47,7 +48,8 @@ public class Role extends AuditDomain {
/** /**
* 角色拥有的权限 * 角色拥有的权限
*/ */
@Reference(Permission.class) @DBRef
@Association(relationTable = "rel_role_permission", field = "role_id", foreignField = "permission_id")
private List<Permission> permissions; private List<Permission> permissions;
/** /**

View File

@ -6,12 +6,14 @@ import com.flyfish.framework.domain.base.AuditDomain;
import com.flyfish.framework.domain.base.IUser; import com.flyfish.framework.domain.base.IUser;
import com.flyfish.framework.enums.UserStatus; import com.flyfish.framework.enums.UserStatus;
import com.flyfish.framework.enums.UserType; import com.flyfish.framework.enums.UserType;
import com.flyfish.framework.r2dbc.mapping.Association;
import com.flyfish.framework.validation.spi.ConditionalGroup; import com.flyfish.framework.validation.spi.ConditionalGroup;
import lombok.*; import lombok.*;
import org.springframework.data.annotation.Reference;
import org.springframework.data.annotation.Transient; import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -70,23 +72,27 @@ public class User extends AuditDomain implements IUser {
* 有效期 * 有效期
*/ */
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")
@Column("valid_date")
private LocalDateTime validDate; private LocalDateTime validDate;
/** /**
* 可操作校区 * 可操作校区
*/ */
@Reference(Department.class) @DBRef
@Association(relationTable = "rel_user_depart", field = "user_id", foreignField = "depart_id")
private List<Department> departments; private List<Department> departments;
/** /**
* 所属角色 * 所属角色
*/ */
@Reference(Role.class) @DBRef
@Association(relationTable = "rel_user_depart", field = "user_id", foreignField = "depart_id")
private List<Role> roles; private List<Role> roles;
/** /**
* 微信openId * 微信openId
*/ */
@Column("open_id")
private String openId; private String openId;
/** /**
@ -103,11 +109,13 @@ public class User extends AuditDomain implements IUser {
/** /**
* 错误次数防止恶意登录 * 错误次数防止恶意登录
*/ */
@Column("error_count")
private Integer errorCount = 0; private Integer errorCount = 0;
/** /**
* 上次登录日期 * 上次登录日期
*/ */
@Column("last_time")
private LocalDateTime lastTime; private LocalDateTime lastTime;
@Override @Override

View File

@ -4,6 +4,7 @@ import com.flyfish.framework.domain.base.AuditDomain;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.springframework.data.annotation.Transient; import org.springframework.data.annotation.Transient;
import org.springframework.data.relational.core.mapping.Column;
import java.util.List; import java.util.List;
@ -14,9 +15,11 @@ public abstract class TreeDomain<T extends TreeDomain<T>> extends AuditDomain {
public static final String ROOT = "0"; public static final String ROOT = "0";
// 父id顶级是0 // 父id顶级是0
@Column("parent_id")
private String parentId; private String parentId;
// 冗余的父ids方便查询 // 冗余的父ids方便查询
@Column("parent_ids")
private List<String> parentIds; private List<String> parentIds;
// 深度遍历标识 // 深度遍历标识

View File

@ -45,8 +45,9 @@ public class R2dbcDataConfig {
} }
@Bean @Bean
public EntityCallback<Domain> referenceR2dbcCallback(R2dbcMetadataManager metadataManager) { public EntityCallback<Domain> referenceR2dbcCallback(R2dbcEntityOperations entityOperations, R2dbcMetadataManager metadataManager) {
return new ReferenceR2dbcCallback(metadataManager); return new ReferenceR2dbcCallback(metadataManager, entityOperations.getDatabaseClient(), entityOperations.getDataAccessStrategy()
.getStatementMapper());
} }
@Bean @Bean

View File

@ -5,8 +5,10 @@ import com.flyfish.framework.domain.base.Qo;
import com.flyfish.framework.query.Queries; import com.flyfish.framework.query.Queries;
import com.flyfish.framework.r2dbc.metadata.R2dbcMetadataManager; import com.flyfish.framework.r2dbc.metadata.R2dbcMetadataManager;
import com.flyfish.framework.r2dbc.metadata.R2dbcTableMetadata; import com.flyfish.framework.r2dbc.metadata.R2dbcTableMetadata;
import com.flyfish.framework.r2dbc.metadata.reference.FieldSetter;
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcAssociation; import com.flyfish.framework.r2dbc.metadata.reference.R2dbcAssociation;
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcCollection; import com.flyfish.framework.r2dbc.metadata.reference.R2dbcCollection;
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcRelation;
import com.flyfish.framework.repository.DefaultReactiveRepository; import com.flyfish.framework.repository.DefaultReactiveRepository;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@ -17,12 +19,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.r2dbc.core.StatementMapper;
import org.springframework.data.r2dbc.mapping.event.AfterConvertCallback; import org.springframework.data.r2dbc.mapping.event.AfterConvertCallback;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.sql.SqlIdentifier; import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.util.CastUtils; import org.springframework.data.util.CastUtils;
import org.springframework.data.util.Lazy; import org.springframework.data.util.Lazy;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.r2dbc.core.PreparedOperation;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.ArrayList; import java.util.ArrayList;
@ -36,6 +43,8 @@ import java.util.stream.Collectors;
public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> { public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
private final R2dbcMetadataManager r2dbcMetadataManager; private final R2dbcMetadataManager r2dbcMetadataManager;
private final DatabaseClient databaseClient;
private final StatementMapper statementMapper;
private Lazy<Map<Class<?>, DefaultReactiveRepository<?>>> repositories; private Lazy<Map<Class<?>, DefaultReactiveRepository<?>>> repositories;
@Override @Override
@ -72,6 +81,7 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
List<Mono<Domain>> signals = new ArrayList<>(); List<Mono<Domain>> signals = new ArrayList<>();
signals.addAll(fetchAssociation(metadata.getAssociations(), accessor)); signals.addAll(fetchAssociation(metadata.getAssociations(), accessor));
signals.addAll(fetchCollections(metadata.getCollections(), accessor)); signals.addAll(fetchCollections(metadata.getCollections(), accessor));
signals.addAll(fetchAssociation())
// 尝试填充一对多关联 // 尝试填充一对多关联
if (CollectionUtils.isNotEmpty(signals)) { if (CollectionUtils.isNotEmpty(signals)) {
@ -111,9 +121,11 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
// 内部查询以对象内的值作为查询条件 // 内部查询以对象内的值作为查询条件
Object value = accessor.getProperty(association.getField()); Object value = accessor.getProperty(association.getField());
if (ObjectUtils.isEmpty(value)) return; if (ObjectUtils.isEmpty(value)) return;
// 准备设置
FieldSetter setter = association.getSetter();
// 查询 // 查询
Mono<Domain> signal = repository.findById(String.valueOf(value)) Mono<Domain> signal = repository.findById(String.valueOf(value))
.map(result -> association.setValue(accessor.getBean(), result)) .map(result -> setter.setValue(accessor.getBean(), result))
.defaultIfEmpty(accessor.getBean()); .defaultIfEmpty(accessor.getBean());
signals.add(signal); signals.add(signal);
}); });
@ -126,9 +138,11 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
String id = accessor.getBean().getId(); String id = accessor.getBean().getId();
// 准备查询 // 准备查询
DefaultReactiveRepository<Domain> repository = getRepository(association.getEntity().getType()); DefaultReactiveRepository<Domain> repository = getRepository(association.getEntity().getType());
// 准备设置
FieldSetter setter = association.getSetter();
// 直接通过外部字段查询 // 直接通过外部字段查询
Mono<Domain> signal = repository.findOne(Queries.where(getColumnName(association.getField())).eq(id).wrap()) Mono<Domain> signal = repository.findOne(Queries.where(getColumnName(association.getField())).eq(id).wrap())
.map(result -> association.setValue(accessor.getBean(), result)) .map(result -> setter.setValue(accessor.getBean(), result))
.defaultIfEmpty(accessor.getBean()); .defaultIfEmpty(accessor.getBean());
signals.add(signal); signals.add(signal);
}); });
@ -154,10 +168,48 @@ public class ReferenceR2dbcCallback implements AfterConvertCallback<Domain> {
String id = accessor.getBean().getId(); String id = accessor.getBean().getId();
// 准备查询 // 准备查询
DefaultReactiveRepository<Domain> repository = getRepository(collection.getEntity().getType()); DefaultReactiveRepository<Domain> repository = getRepository(collection.getEntity().getType());
// 准备设置
FieldSetter setter = collection.getSetter();
// 直接通过外部字段查询 // 直接通过外部字段查询
Mono<Domain> signal = repository.findAll(Queries.where(getColumnName(collection.getField())).eq(id).wrap()) Mono<Domain> signal = repository.findAll(Queries.where(getColumnName(collection.getField())).eq(id).wrap())
.collectList() .collectList()
.map(result -> collection.setValue(accessor.getBean(), result)) .map(result -> setter.setValue(accessor.getBean(), result))
.defaultIfEmpty(accessor.getBean());
signals.add(signal);
});
}
return signals;
}
/**
* 拉取多对多关联数据
*
* @param relations 多对多关联信息
* @param accessor 本对象的属性访问器
* @return 结果
*/
private List<Mono<Domain>> fetchRelations(List<R2dbcRelation> relations, PersistentPropertyAccessor<Domain> accessor) {
List<Mono<Domain>> signals = new ArrayList<>();
if (CollectionUtils.isNotEmpty(relations)) {
// 生成DatabaseClient执行sql语句查询
relations.forEach(relation -> {
// 准备目标对象的repo
DefaultReactiveRepository<Domain> repository = getRepository(relation.getEntity().getType());
// 准备查询参数
String id = accessor.getBean().getId();
StatementMapper.SelectSpec select = statementMapper.createSelect("rel_table")
.withProjection(relation.getForeignField()).withCriteria(Criteria.where(relation.getField()).is(id));
PreparedOperation<?> operation = statementMapper.getMappedObject(select);
// 执行查询
Flux<String> ids = databaseClient.sql(operation)
.map(row -> row.get(0, String.class))
.all();
// 准备设置
FieldSetter setter = relation.getSetter();
// 查询最终结果
Mono<Domain> signal = repository.findAllById(ids)
.collectList()
.map(result -> setter.setValue(accessor.getBean(), result))
.defaultIfEmpty(accessor.getBean()); .defaultIfEmpty(accessor.getBean());
signals.add(signal); signals.add(signal);
}); });

View File

@ -1,4 +1,4 @@
package com.flyfish.framework.annotations.relation; package com.flyfish.framework.r2dbc.mapping;
import org.springframework.data.annotation.Transient; import org.springframework.data.annotation.Transient;
@ -31,4 +31,12 @@ public @interface Association {
* 与field互斥同时指定永远都以field为主 * 与field互斥同时指定永远都以field为主
*/ */
String foreignField() default ""; String foreignField() default "";
/**
* 关系表针对多对多的情况
* 配置了该项的情况下field和foreignField都为该表上的字段
*
* @return 结果
*/
String relationTable() default "";
} }

View File

@ -1,9 +1,11 @@
package com.flyfish.framework.r2dbc.metadata; package com.flyfish.framework.r2dbc.metadata;
import com.flyfish.framework.annotations.Property; import com.flyfish.framework.annotations.Property;
import com.flyfish.framework.r2dbc.mapping.Association;
import com.flyfish.framework.r2dbc.metadata.reference.FieldSetter; import com.flyfish.framework.r2dbc.metadata.reference.FieldSetter;
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcAssociation; import com.flyfish.framework.r2dbc.metadata.reference.R2dbcAssociation;
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcCollection; import com.flyfish.framework.r2dbc.metadata.reference.R2dbcCollection;
import com.flyfish.framework.r2dbc.metadata.reference.R2dbcRelation;
import lombok.Data; import lombok.Data;
import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentProperty;
@ -29,6 +31,9 @@ public class R2dbcTableMetadata {
@Property("一对多关联信息") @Property("一对多关联信息")
private List<R2dbcCollection> collections = new ArrayList<>(); private List<R2dbcCollection> collections = new ArrayList<>();
@Property("多对多关联信息")
private List<R2dbcRelation> relations = new ArrayList<>();
public R2dbcTableMetadata(PersistentEntity<?, ?> entity) { public R2dbcTableMetadata(PersistentEntity<?, ?> entity) {
this.entity = entity; this.entity = entity;
} }
@ -41,4 +46,8 @@ public class R2dbcTableMetadata {
this.collections.add(R2dbcCollection.of(entity, property, setter)); this.collections.add(R2dbcCollection.of(entity, property, setter));
} }
public void addRelation(PersistentEntity<?, ?> entity, Association association, FieldSetter setter) {
this.relations.add(R2dbcRelation.of(entity, association, setter));
}
} }

View File

@ -1,6 +1,6 @@
package com.flyfish.framework.r2dbc.metadata.impl; package com.flyfish.framework.r2dbc.metadata.impl;
import com.flyfish.framework.annotations.relation.Association; import com.flyfish.framework.r2dbc.mapping.Association;
import com.flyfish.framework.domain.base.Domain; import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.r2dbc.metadata.R2dbcMetadataManager; import com.flyfish.framework.r2dbc.metadata.R2dbcMetadataManager;
import com.flyfish.framework.r2dbc.metadata.R2dbcTableMetadata; import com.flyfish.framework.r2dbc.metadata.R2dbcTableMetadata;
@ -105,6 +105,11 @@ public class SimpleR2dbcMetadataManager implements R2dbcMetadataManager {
if (ClassUtils.isAssignable(type, Domain.class)) { if (ClassUtils.isAssignable(type, Domain.class)) {
// 目标类型 // 目标类型
PersistentEntity<?, ?> targetEntity = r2dbcMappingContext.getRequiredPersistentEntity(type); PersistentEntity<?, ?> targetEntity = r2dbcMappingContext.getRequiredPersistentEntity(type);
// 多对多关联
if (StringUtils.isNotBlank(association.relationTable())) {
metadata.addRelation(targetEntity, association, setter);
return;
}
// 一对一关联 // 一对一关联
if (StringUtils.isNotBlank(association.field())) { if (StringUtils.isNotBlank(association.field())) {
// 获取内部属性 // 获取内部属性
@ -131,6 +136,11 @@ public class SimpleR2dbcMetadataManager implements R2dbcMetadataManager {
if (null == entityType) return; if (null == entityType) return;
// 目标类型 // 目标类型
PersistentEntity<?, ?> targetEntity = r2dbcMappingContext.getRequiredPersistentEntity(entityType); PersistentEntity<?, ?> targetEntity = r2dbcMappingContext.getRequiredPersistentEntity(entityType);
// 多对多关联
if (StringUtils.isNotBlank(association.relationTable())) {
metadata.addRelation(targetEntity, association, setter);
return;
}
// 一对多关联仅支持外部字段 // 一对多关联仅支持外部字段
if (StringUtils.isNotBlank(association.foreignField())) { if (StringUtils.isNotBlank(association.foreignField())) {
// 获取外部属性 // 获取外部属性

View File

@ -1,8 +1,14 @@
package com.flyfish.framework.r2dbc.metadata.reference; package com.flyfish.framework.r2dbc.metadata.reference;
import com.flyfish.framework.domain.base.Domain;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@FunctionalInterface @FunctionalInterface
public interface FieldSetter extends BiConsumer<Object, Object> { public interface FieldSetter extends BiConsumer<Object, Object> {
default <T extends Domain> T setValue(T obj, Object value) {
accept(obj, value);
return obj;
}
} }

View File

@ -1,7 +1,6 @@
package com.flyfish.framework.r2dbc.metadata.reference; package com.flyfish.framework.r2dbc.metadata.reference;
import com.flyfish.framework.annotations.Property; import com.flyfish.framework.annotations.Property;
import com.flyfish.framework.domain.base.Domain;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentEntity;
@ -27,9 +26,4 @@ public class R2dbcAssociation {
public static R2dbcAssociation of(PersistentEntity<?, ?> entity, PersistentProperty<?> field, FieldSetter setter, boolean inner) { public static R2dbcAssociation of(PersistentEntity<?, ?> entity, PersistentProperty<?> field, FieldSetter setter, boolean inner) {
return new R2dbcAssociation(entity, field, setter, inner); return new R2dbcAssociation(entity, field, setter, inner);
} }
public <T extends Domain> T setValue(T obj, Object value) {
setter.accept(obj, value);
return obj;
}
} }

View File

@ -1,7 +1,6 @@
package com.flyfish.framework.r2dbc.metadata.reference; package com.flyfish.framework.r2dbc.metadata.reference;
import com.flyfish.framework.annotations.Property; import com.flyfish.framework.annotations.Property;
import com.flyfish.framework.domain.base.Domain;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentEntity;
@ -24,9 +23,4 @@ public class R2dbcCollection {
public static R2dbcCollection of(PersistentEntity<?, ?> entity, PersistentProperty<?> field, FieldSetter setter) { public static R2dbcCollection of(PersistentEntity<?, ?> entity, PersistentProperty<?> field, FieldSetter setter) {
return new R2dbcCollection(entity, field, setter); return new R2dbcCollection(entity, field, setter);
} }
public <T extends Domain> T setValue(T obj, Object value) {
setter.accept(obj, value);
return obj;
}
} }

View File

@ -0,0 +1,37 @@
package com.flyfish.framework.r2dbc.metadata.reference;
import com.flyfish.framework.annotations.Property;
import com.flyfish.framework.r2dbc.mapping.Association;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.mapping.PersistentEntity;
/**
* 多对多关系
*
* @author wangyu
*/
@Data
@Property("多对多关系")
@AllArgsConstructor
public class R2dbcRelation {
@Property("关联实体类")
private PersistentEntity<?, ?> entity;
@Property("关系表名称")
private String tableName;
@Property("关系表本实体id字段")
private String field;
@Property("关系表外部实体id字段")
private String foreignField;
@Property("目标值设置器")
private FieldSetter setter;
public static R2dbcRelation of(PersistentEntity<?, ?> entity, Association association, FieldSetter setter) {
return new R2dbcRelation(entity, association.relationTable(), association.field(), association.foreignField(), setter);
}
}

View File

@ -49,7 +49,6 @@ public class QueryingR2dbcReactiveRepository<T extends Domain> extends SimpleR2d
super(entity, entityOperations, converter); super(entity, entityOperations, converter);
this.entity = entity; this.entity = entity;
this.entityOperations = entityOperations; this.entityOperations = entityOperations;
} }
/** /**

View File

@ -1,6 +1,6 @@
package com.flyfish.framework.r2dbc.domain; package com.flyfish.framework.r2dbc.domain;
import com.flyfish.framework.annotations.relation.Association; import com.flyfish.framework.r2dbc.mapping.Association;
import com.flyfish.framework.domain.base.AuditDomain; import com.flyfish.framework.domain.base.AuditDomain;
import com.flyfish.framework.r2dbc.domain.reference.TestAsso; import com.flyfish.framework.r2dbc.domain.reference.TestAsso;
import com.flyfish.framework.r2dbc.domain.reference.TestChild; import com.flyfish.framework.r2dbc.domain.reference.TestChild;

View File

@ -0,0 +1,15 @@
CREATE TABLE IF NOT EXISTS `test`
(
`id` VARCHAR(36) NOT NULL COMMENT '主键',
`code` VARCHAR(32) NOT NULL COMMENT '编码',
`name` VARCHAR(100) NOT NULL COMMENT '名称',
`other_id` VARCHAR(36) NULL COMMENT '其他id',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`modify_time` DATETIME NOT NULL COMMENT '修改时间',
`creator` VARCHAR(36) NULL COMMENT '创建人名称',
`creator_id` VARCHAR(36) NULL COMMENT '创建人id',
`modifier` VARCHAR(36) NULL COMMENT '修改人名称',
`modifier_id` VARCHAR(36) NULL COMMENT '修改人id',
`delete` BIT(1) NOT NULL DEFAULT b'0',
PRIMARY KEY (`id`)
) COMMENT '测试表';