动态依据模版生成bean对象并生成crud方法的问题

 在最近的项目中,领导需要依据配置的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目录下生成了,但由于没有编译,无法被其他类使用,后续再看看有没有啥办法,目前只能手动了

猜你喜欢

转载自blog.csdn.net/u012440725/article/details/130487434