在最近的项目中,领导需要依据配置的json文件来生成对象,然后生成jpa的crud接口如下:
1.类的配置文件
{
"group": "asset",
"engine": "RDMS",
"storeName": "asset_account",
"cname": "账号表",
"name": "asset_account",
"unique": "unique_url",
"comment": "账号表",
"show":true,
"order":800,
"columns": [
{
"storeName": "id",
"label": "",
"cname": "主键ID",
"name": "id",
"type": "String",
"comment": "主键ID",
"nullable": false,
"index": true,
"queryable": false,
"unique": true
},
{
"storeName": "acc_name",
"label": "",
"cname": "账号名称",
"name": "accName",
"type": "String",
"comment": "账号名称",
"nullable": false,
"index": true,
"queryable": true,
"unique": true
},
{
"storeName": "acc_alias",
"label": "",
"cname": "账号别名",
"name": "accAlias",
"type": "String",
"comment": "账号别名",
"nullable": true,
"index": false,
"queryable": false,
"unique": false
},
{
"storeName": "acc_tags",
"label": "",
"cname": "账号标签",
"name": "accTags",
"type": "String",
"comment": "账号标签",
"nullable": true,
"index": false,
"queryable": false,
"unique": false
},
{
"storeName": "oauth_type",
"label": "",
"cname": "权限类型",
"name": "oauthType",
"type": "String",
"comment": "权限类型",
"nullable": true,
"index": false,
"queryable": false,
"unique": false
},
{
"storeName": "unique_url",
"label": "",
"cname": "唯一标识",
"name": "uniqueUrl",
"type": "String",
"comment": "唯一标识",
"nullable": false,
"index": false,
"queryable": false,
"unique": true
},
{
"storeName": "plat_cate_unique_url",
"label": "",
"cname": "账号类型",
"name": "platCateUniqueUrl",
"type": "String",
"comment": "账号类型",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "begin_time",
"label": "",
"cname": "开始时间",
"name": "beginTime",
"type": "datatime",
"comment": "开始时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "end_time",
"label": "",
"cname": "结束时间",
"name": "endTime",
"type": "datatime",
"comment": "结束时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "password",
"label": "",
"cname": "密码",
"name": "password",
"type": "String",
"comment": "密码",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "password_expire_time",
"label": "",
"cname": "密码过期时间",
"name": "passwordExpireTime",
"type": "datatime",
"comment": "密码过期时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "create_time",
"label": "",
"cname": "创建时间",
"name": "createTime",
"type": "datatime",
"comment": "创建时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "update_time",
"label": "",
"cname": "修改时间",
"name": "updateTime",
"type": "datatime",
"comment": "修改时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "deleted",
"label": "",
"cname": "删除标记",
"name": "deleted",
"type": "int",
"comment": "删除标记",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "creator_id",
"label": "",
"cname": "创建人id",
"name": "creatorId",
"type": "String",
"comment": "创建人id",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "last_modifier",
"label": "",
"cname": "最后修改人",
"name": "lastModifier",
"type": "String",
"comment": "最后修改人",
"index": false,
"nullable": true,
"queryable": false,
"unique": true
},
{
"storeName": "acc_remark",
"label": "",
"cname": "账号备注",
"name": "accRemark",
"type": "String",
"comment": "账号备注",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "json_properties",
"label": "",
"cname": "账号属性",
"name": "jsonProperties",
"type": "String",
"comment": "账号属性",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "login_type",
"label": "",
"cname": "登录方式",
"name": "loginType",
"type": "String",
"comment": "登录方式",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "port",
"label": "",
"cname": "端口",
"name": "port",
"type": "String",
"comment": "端口",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "app_id",
"label": "",
"cname": "应用id",
"name": "appId",
"type": "String",
"comment": "应用id",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "dev_id",
"label": "",
"cname": "设备id",
"name": "devId",
"type": "String",
"comment": "设备id",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "comp_id",
"label": "",
"cname": "组件id",
"name": "compId",
"type": "String",
"comment": "组件id",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "acc_status",
"label": "",
"cname": "账号状态",
"name": "accStatus",
"type": "bool",
"comment": "账号状态",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "label",
"label": "",
"cname": "标签",
"name": "label",
"type": "String",
"comment": "标签",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "main_account_uuid",
"label": "",
"cname": "所属主账号的UUID",
"name": "mainAccountUuid",
"type": "String",
"comment": "所属主账号的UUID",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "account_role",
"label": "",
"cname": "账号角色集合",
"name": "accountRole",
"type": "String",
"comment": "账号角色集合",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "account_jurisdiction",
"label": "",
"cname": "账号权限集合",
"name": "accountJurisdiction",
"type": "String",
"comment": "账号权限集合",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "resource_type",
"label": "",
"cname": "资源类型",
"name": "resourceType",
"type": "int",
"comment": "资源类型",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "privilege",
"label": "",
"cname": "是否特权账号",
"name": "privilege",
"type": "int",
"comment": "是否特权账号",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "real_name_authenticated",
"label": "",
"cname": "是否实名认证",
"name": "realNameAuthenticated",
"type": "int",
"comment": "是否实名认证",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "employee_effective_time",
"label": "",
"cname": "所属员工生效时间",
"name": "employeeEffectiveTime",
"type": "datatime",
"comment": "所属员工生效时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "account_effective_time",
"label": "",
"cname": "账号生效时间",
"name": "accountEffectiveTime",
"type": "datatime",
"comment": "账号生效时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "account_expiration_time",
"label": "",
"cname": "账号失效时间",
"name": "accountExpirationTime",
"type": "datatime",
"comment": "账号失效时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "account_cancellation_time",
"label": "",
"cname": "账号注销时间",
"name": "accountCancellationTime",
"type": "datatime",
"comment": "账号注销时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "password_authentication_type",
"label": "",
"cname": "认证类型",
"name": "passwordAuthenticationType",
"type": "int",
"comment": "认证类型",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "password_expiration_date",
"label": "",
"cname": "密码到期时间",
"name": "passwordExpirationDate",
"type": "datatime",
"comment": "密码到期时间",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "server_id",
"label": "",
"cname": "服务id",
"name": "serverId",
"type": "String",
"comment": "服务id",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "per_id",
"label": "",
"cname": "人员id",
"name": "perId",
"type": "String",
"comment": "人员id",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
},
{
"storeName": "data_source",
"label": "",
"cname": "数据来源",
"name": "dataSource",
"type": "int",
"comment": "数据来源",
"index": false,
"nullable": true,
"queryable": false,
"unique": false
}
],
"relations": [
{
"type": "hasOne",
"model": "asset_personnel",
"key": "id",
"foreign": "per_id",
"fieldName": "perData",
"cascadingAssociation": "1",
"relationType": {
"code": "0",
"name": "人员名称",
"FieldName": "id",
"linkField": "perName",
"desc": "perId"
}
},
{
"type": "hasOne",
"model": "asset_device",
"key": "id",
"foreign": "dev_id",
"fieldName": "deviceData",
"cascadingAssociation": "1",
"relationType": {
"code": "0",
"name": "设备名称",
"FieldName": "id",
"linkField": "devName",
"desc": "devId"
}
},
{
"type": "hasOne",
"model": "asset_business_app",
"key": "id",
"foreign": "app_id",
"fieldName": "appData",
"cascadingAssociation": "1",
"relationType": {
"code": "1",
"name": "应用名称",
"FieldName": "id",
"linkField": "appName",
"desc": "appId"
}
}
],
"option": {
"optionName": "",
"timestamps": true,
"soft_deletes": true
}
}
2.在启动时 解析json文件并生成class文件
private static String generateJavaSource(String packageName, Entity entity) {
StringBuilder sb = new StringBuilder();
//包名
sb.append("package " + packageName + ";\n");
//引入的依赖
sb.append("import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;\n");
sb.append("import com.alibaba.fastjson.annotation.JSONField;\n");
sb.append("import com.fasterxml.jackson.annotation.JsonFormat;\n");
sb.append("import com.fasterxml.jackson.annotation.JsonProperty;\n");
sb.append("import io.swagger.annotations.ApiModelProperty;\n");
sb.append("import lombok.AllArgsConstructor;\n");
sb.append("import lombok.Data;\n");
sb.append("import lombok.NoArgsConstructor;\n");
sb.append("import org.hibernate.annotations.DynamicUpdate;\n");
sb.append("import org.springframework.data.annotation.CreatedDate;\n");
sb.append("import org.springframework.data.annotation.LastModifiedDate;\n");
sb.append("import org.springframework.data.jpa.domain.support.AuditingEntityListener; \n");
sb.append("import javax.persistence.*; \n");
sb.append("import javax.validation.constraints.NotNull;\n");
sb.append("import javax.validation.constraints.Pattern;\n");
sb.append("import java.util.Date;\n");
sb.append("import lombok.EqualsAndHashCode;\n");
sb.append("import java.util.Objects;\n");
sb.append("import java.util.Optional;\n");
//类上的注解
sb.append("@ExcelIgnoreUnannotated \t\n");
sb.append("@Entity \t\n");
sb.append("@Table(name = \"" + entity.getStoreName() + "\") \t\n");
sb.append("@Data \t\n");
sb.append("@EqualsAndHashCode(callSuper = false) \t\n");
sb.append("@AllArgsConstructor \t\n");
sb.append("@NoArgsConstructor \t\n");
sb.append("@DynamicUpdate \t\n");
sb.append("@EntityListeners(AuditingEntityListener.class) \n");
//类名
sb.append("public class " + UnderlineToCamelUtils.camel2EntityPo(entity.getStoreName()) + " extends BasePo { \n");
//属性
List<Column> columns = entity.getColumns();
columns.forEach(item -> {
String fieldType = getFieldType(item.getType());
sb.append("@Column(name = \"" + item.getStoreName() + "\")\n");
sb.append("public " + fieldType + " " + UnderlineToCamelUtils.underlineToHump(item.getStoreName()) + "; \n");
});
sb.append("@Override\n" +
" public boolean equals(Object o) {\n" +
" if (this == o) return true;\n" +
" if (o == null || getClass() != o.getClass()) return false;\n" +
" if (!super.equals(o)) return false;\n" +
" AssetAccountPo that = (AssetAccountPo) o;\n" +
" return id.equals(that.id);\n" +
" }\n" +
"\n" +
" @Override\n" +
" public int hashCode() {\n" +
" return Objects.hash(super.hashCode(), id);\n" +
" }\n");
//类结束
sb.append("} \n");
return sb.toString();
}
3.编译类并加载到内存中
private static final String CLASS_OUTPUT_DIR = "./target/classes/";
public Class<?> compile(String className, String javaSourceCode) throws Exception {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
try (MemoryClassLoader classLoader = new MemoryClassLoader()) {
JavaFileObject javaFileObject = new MemoryJavaFileObject(className, javaSourceCode);
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(javaFileObject);
JavaFileManager.Location outputLocation = StandardLocation.CLASS_OUTPUT;
fileManager.setLocation(outputLocation, Arrays.asList(new File(CLASS_OUTPUT_DIR)));
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, compilationUnits);
if (!task.call()) {
throw new IllegalStateException("Failed to compile");
}
Class<?> clazz = classLoader.loadClass(className);
return clazz;
}
}
private static class MemoryJavaFileObject extends SimpleJavaFileObject {
private final String javaSourceCode;
protected MemoryJavaFileObject(String className, String javaSourceCode) {
super(URI.create("string:///" + className.replaceAll("\\.", "/") + Kind.SOURCE.extension), Kind.SOURCE);
this.javaSourceCode = javaSourceCode;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return javaSourceCode;
}
}
private static class MemoryClassLoader extends ClassLoader implements AutoCloseable {
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = getClassData(name);
return defineClass(name, bytes, 0, bytes.length);
}
private byte[] getClassData(String className) {
String fileName = className.replaceAll("\\.", "/") + ".class";
File classFile = new File(CLASS_OUTPUT_DIR, fileName);
try {
byte[] bytes = Files.readAllBytes(classFile.toPath());
classFile.delete();
return bytes;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@SneakyThrows
@Override
public void close() throws Exception {
super.finalize();
}
}
4.遇到的问题,动态生成的类确实到class目录下生成了,但由于没有编译,无法被其他类使用,后续再看看有没有啥办法,目前只能手动了