POJO生成器v1

POJO生成器


定义一个接口先

package util.generator;

import java.util.Map;

public interface Generator<T> {

  T generate(Map config);

}

示例配置文件GeneratorTestClass.yml

ignores:
  - log

fields:
  id:
    $generator: ?.StringUuidGenerator
  transmissionNumber:
    len: 35
  requests:
    len: 3

大BOSS来了,反射获取类所有字段,读取类配置文件,再根据配置使用apache.common.lang3生成值

package util.generator;

import com.google.common.collect.ImmutableMap;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.yaml.snakeyaml.Yaml;
import util.generator.exception.BuildGenerateConfigException;
import util.generator.exception.GeneratorException;
import util.generator.exception.InvalidConfigurationException;

@Slf4j
public final class ObjectGenerator {

  private ObjectGenerator() {
  }

  private static final String CONFIG_DIR = "generating-config";

  private static final Map<Class, Function<FieldConfig, ?>> GENERATORS = ImmutableMap
      .<Class, Function<FieldConfig, ?>>builder()
      .put(String.class, ObjectGenerator::genString)
      .put(UUID.class, ObjectGenerator::genUUID)
      .put(ZonedDateTime.class, ObjectGenerator::genZonedDateTime)
      .put(Date.class, ObjectGenerator::genDate)
      .put(Boolean.class, ObjectGenerator::genBoolean)
      .put(boolean.class, ObjectGenerator::genBoolean)
      .put(Integer.class, ObjectGenerator::genInteger)
      .put(int.class, ObjectGenerator::genInteger)
      .put(Long.class, ObjectGenerator::genLong)
      .put(long.class, ObjectGenerator::genLong)
      .put(Double.class, ObjectGenerator::genDouble)
      .put(double.class, ObjectGenerator::genDouble)
      .put(BigDecimal.class, ObjectGenerator::genBigDecimal)
      .build();

  /**
   * CustomizedGeneratorInstanceCache cache all customized generators' instance, avoid to create
   * multi instance of the same generator.
   */
  private static Map<Class<Generator>, Generator> customizedGeneratorInstanceCache = new HashMap<>();

  /**
   * CustomizedGenerators uses to get generator efficiently with TypeSignature, when we need to
   * generate an instance again for a class, we don't need to use Class.forName to load AbstractGenerator,
   * we could get appropriate generator with the field's TypeSignature directly.
   */
  private static Map<TypeSignature, Generator> customizedGenerators = new HashMap<>();

  private static final String CONFIG_NAME_GENERATOR = "$generator";
  private static final String CONFIG_NAME_LIST_ELEM = "$listElem";
  private static final String CONFIG_RELATED_CLASS_PATH = "?";

  /**
   * Cache configurations, content: className -> configMap
   */
  private static Map<String, Map> configCache = new HashMap<>();

  public static <T> T generate(Class<T> targetClass, String... firstIgnores) {
    return generate(targetClass, null, firstIgnores);
  }

  /**
   * <p>Generate fields' value for target object. Default supported type:</p>
   * <ul>
   *   <li>String: {@link ObjectGenerator#genString}</li>
   *   <li>UUID: {@link ObjectGenerator#genUUID}</li>
   *   <li>ZonedDateTimeGenerator: {@link ObjectGenerator#genZonedDateTime}</li>
   *   <li>Integer: {@link ObjectGenerator#genInteger}</li>
   *   <li>Long: {@link ObjectGenerator#genLong}</li>
   *   <li>Double: {@link ObjectGenerator#genDouble}</li>
   *   <li>BigDecimal: {@link ObjectGenerator#genBigDecimal}</li>
   * </ul>
   * <p>AbstractGenerator will read and cache configuration from a file with path <code>classpath:{className}.yml</code>.</p>
   *
   * @param targetClass target object
   * @param firstConfigs customize field generating configurations, which will overwrite the
   * configurations read from config file
   * @param firstIgnores declare which properties should be ignored
   * @return T target object
   */
  @SuppressWarnings("unchecked")
  public static <T> T generate(Class<T> targetClass,
      Map<String, Map<String, Object>> firstConfigs,
      String... firstIgnores) {
    Assert.notNull(targetClass, "Parameter targetClass must be non-null");

    if (GENERATORS.containsKey(targetClass)) {
      throw new GeneratorException("targetClass must be customized type.");
    }

    // try create new instance for target class

    Object target;
    try {
      target = targetClass.newInstance();
    } catch (Exception e) {
      throw new GeneratorException("Failed to create a new instance of target class " +
          targetClass.getSimpleName() + ".");
    }

    String className = targetClass.getSimpleName();

    //  read configuration

    loadConfig(className);

    Map fieldsConfig = getFieldsConfig(className);
    Set ignoresConfig = getIgnoresConfig(className);

    if (ignoresConfig.isEmpty()) {
      ignoresConfig = new HashSet(Arrays.asList(firstIgnores));
    } else {
      ignoresConfig.addAll(Arrays.asList(firstIgnores));
    }

    if (Objects.isNull(firstConfigs)) {
      firstConfigs = Collections.EMPTY_MAP;
    }

    // generate object

    Class<?> objectClass = targetClass;
    while (!Object.class.equals(objectClass)) {
      try {
        for (Field field : objectClass.getDeclaredFields()) {
          String fieldName = field.getName();

          // skip static or final field
          int modifiers = field.getModifiers();
          if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) {
            log.debug("{}.{} - Field has been skipped because it has static or final modifier.",
                className, fieldName);
            continue;
          }

          // skip field need be ignored
          if (ignoresConfig.contains(fieldName)) {
            continue;
          }

          // set field accessible
          field.setAccessible(true);

          // if target field need an enum value, generate value directly
          Class<?> fieldType = field.getType();
          if (fieldType.isEnum()) {
            Object[] enumValues = fieldType.getEnumConstants();
            // cannot generate value with empty enum
            if (enumValues.length == 0) {
              throw new GeneratorException("Couldn't generate a value for field " +
                  fieldName + "using empty enum" + fieldType.getSimpleName() + ".");
            }
            field.set(target, enumValues[RandomUtils.nextInt(0, enumValues.length)]);
            continue;
          }

          // get field configuration
          Object objFieldConfig = fieldsConfig.get(fieldName);
          Map fieldConfig = (objFieldConfig instanceof Map) ?
              (Map) objFieldConfig : Collections.EMPTY_MAP;

          // merge first configuration
          Map<String, Object> firstConfig = firstConfigs.get(fieldName);
          if (Objects.nonNull(firstConfig)) {
            if (fieldConfig.isEmpty()) {
              fieldConfig = firstConfig;
            } else {
              fieldConfig.putAll(firstConfig);
            }
          }

          field.set(target, generate(className, field, fieldConfig, objectClass));
        }
      } catch (IllegalAccessException e) {
        throw new GeneratorException(
            "Failed to set field value of object with class " + className + ".", e);
      }

      // turn to super class
      objectClass = objectClass.getSuperclass();
    }
    return targetClass.cast(target);
  }

  private static Object generate(String baseClassName, Field field,
      Map<String, Object> fieldConfig, Class<?> objectClass) {
    try {
      // use customized generator or standard generator
      Object generatorName = fieldConfig.get(CONFIG_NAME_GENERATOR);
      if (generatorName instanceof String) {
        return generateWithCustomizedGenerator(field, fieldConfig, objectClass,
            (String) generatorName);
      } else if (List.class.equals(field.getType())) {
        return generateListField(field, fieldConfig, objectClass, baseClassName);
      } else {
        return generateWithStandardGenerator(field, fieldConfig, baseClassName);
      }
    } catch (ClassNotFoundException e) {
      throw new GeneratorException("Couldn't find customized generator.", e);
    } catch (InstantiationException e) {
      throw new GeneratorException("Failed to instantiate generator.", e);
    } catch (IllegalAccessException e) {
      throw new GeneratorException(
          "Failed to set field value of object with class " + baseClassName + ".", e);
    }
  }

  private static Object generateWithCustomizedGenerator(Field field,
      Map<String, Object> fieldConfig,
      Class<?> objectClass, String generatorName)
      throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    // replace CONFIG_RELATED_CLASS_PATH with this class's package name
    if (generatorName.startsWith(CONFIG_RELATED_CLASS_PATH)) {
      String packageName = ObjectGenerator.class.getPackage().getName();
      generatorName = generatorName.replace(CONFIG_RELATED_CLASS_PATH, packageName);
    }
    Class<?> generatorClass = Class.forName(generatorName);
    if (!Generator.class.isAssignableFrom(generatorClass)) {
      throw new GeneratorException("Customized generator " + generatorClass.getSimpleName() +
          " must implement AbstractGenerator interface.");
    }

    // get a cached or new instance of specified generator
    Generator generator = getCustomizedGenerator(
        new TypeSignature(field.getName(), objectClass),
        (Class<Generator>) generatorClass);

    return generator.generate(fieldConfig);
  }

  private static Object generateListField(Field field, Map<String, Object> fieldConfig,
      Class<?> objectClass, String baseClassName)
      throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    // len: list size, default 3

    String fieldName = field.getName();

    // determine element type
    ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
    Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();
    if (actualTypeArgs.length == 0) {
      throw new GeneratorException("Failed to determine parameterized type of list type field "
          + fieldName + " for class " + baseClassName + ".");
    }
    Class elemClass = (Class) actualTypeArgs[0];

    // read list config
    FieldConfig config = FieldConfig.of(fieldConfig);
    int len = config.get("len", Integer::valueOf, 3);

    // generate list
    Object tmp = config.get(CONFIG_NAME_LIST_ELEM);
    FieldConfig elemConfig;
    if (Objects.isNull(tmp)) {
      elemConfig = FieldConfig.of(Collections.EMPTY_MAP);
    } else if (tmp instanceof Map) {
      elemConfig = FieldConfig.of((Map) tmp);
    } else {
      throw new GeneratorException(baseClassName + "." + fieldName
          + "elemConfig of must be a map, not " + tmp.getClass());
    }

    // generate list
    List list = new ArrayList<>();
    if (elemConfig.containsKey(CONFIG_NAME_GENERATOR)) {
      for (int i = 0; i < len; i++) {
        list.add(generateWithCustomizedGenerator(field, elemConfig.config,
            objectClass, elemConfig.get(CONFIG_NAME_GENERATOR, "")));
      }
    } else if (GENERATORS.containsKey(elemClass)) {
      Function<FieldConfig, ?> generator = GENERATORS.get(elemClass);
      for (int i = 0; i < len; i++) {
        list.add(generator.apply(elemConfig));
      }
    } else {
      if (!elemConfig.isEmpty()) {
        log.warn("{}.{} - $listElem option only works on non-customized type.", baseClassName,
            fieldName);
      }
      for (int i = 0; i < len; i++) {
        list.add(ObjectGenerator.generate(elemClass));
      }
    }
    return list;
  }

  private static Object generateWithStandardGenerator(Field field, Map<String, Object> fieldConfig,
      String baseClassName) {
    Function<FieldConfig, ?> generator = GENERATORS.get(field.getType());
    if (Objects.nonNull(generator)) {
      return generator.apply(FieldConfig.of(fieldConfig));
    } else {
      throw new GeneratorException(baseClassName + "." + field.getName()
          + " - Couldn't find any appropriate generator for type "
          + field.getType() + ".");
    }
  }

  private static void loadConfig(String className) {
    String configPath = new StringBuilder()
        .append(CONFIG_DIR).append('/')
        .append(className).append(".yml")
        .toString();
    ClassPathResource res = new ClassPathResource(configPath);
    try {
      Map config = new Yaml().load(res.getInputStream());
      configCache.put(className, config == null ? Collections.EMPTY_MAP : config);
    } catch (FileNotFoundException e) {
      log.debug("Could not find configuration file for class " + className + ".");
    } catch (IOException e) {
      throw new GeneratorException("Failed to read configuration of class " + className + ".", e);
    }
  }

  private static Map getFieldsConfig(String className) throws InvalidConfigurationException {
    Map config = configCache.get(className);
    if (config != null) {
      Object obj = config.get("fields");
      if (obj != null) {
        if (obj instanceof Map) {
          return (Map) obj;
        } else {
          throw new InvalidConfigurationException("Element 'fields' must be a map.");
        }
      }
    }
    return Collections.EMPTY_MAP;
  }

  @SuppressWarnings("unchecked")
  private static Set getIgnoresConfig(String className) throws InvalidConfigurationException {
    Map config = configCache.get(className);
    if (config != null) {
      Object obj = config.get("ignores");
      if (obj != null) {
        if (obj instanceof List) {
          return new HashSet((List) obj);
        } else {
          throw new InvalidConfigurationException("Element 'ignores' must be a list.");
        }
      }
    }
    return Collections.EMPTY_SET;
  }

  private static class TypeSignature {

    String fieldName;
    Class baseClass;

    TypeSignature(String fieldName, Class baseClass) {
      this.fieldName = fieldName;
      this.baseClass = baseClass;
    }

    @Override
    public boolean equals(Object object) {
      if (!(object instanceof TypeSignature)) {
        return false;
      }
      TypeSignature t = (TypeSignature) object;
      return ObjectUtils.nullSafeEquals(fieldName, t.fieldName)
          && ObjectUtils.nullSafeEquals(baseClass, t.baseClass);
    }

    @Override
    public int hashCode() {
      return fieldName.hashCode() ^ baseClass.hashCode();
    }
  }

  /**
   * Get customized generator,
   *
   * @param typeSignature TypeSignature
   * @param generatorClass Customized generator's class
   * @return AbstractGenerator instance
   * @throws IllegalAccessException failed to instantiate generator
   * @throws InstantiationException failed to instantiate generator
   */
  private static Generator getCustomizedGenerator(TypeSignature typeSignature,
      Class<Generator> generatorClass) throws IllegalAccessException, InstantiationException {
    // try to get the instance bound to this typeSignature
    Generator generator = customizedGenerators.get(typeSignature);
    if (generator == null) {
      // try to get the instance from instanceCache
      generator = customizedGeneratorInstanceCache.get(generatorClass);
      if (generator == null) {
        // create a new instance
        generator = generatorClass.newInstance();
        customizedGeneratorInstanceCache.put(generatorClass, generator);
      }
      customizedGenerators.put(typeSignature, generator);
    }
    return generator;
  }

  private static class FieldConfig {

    Map config;

    FieldConfig(Map config) {
      this.config = config;
    }

    static FieldConfig of(Map config) {
      return new FieldConfig(config);
    }

    <T> T get(String name, T defaultValue) {
      Object tmp = config.get(name);
      try {
        return tmp != null ? (T) tmp : defaultValue;
      } catch (NumberFormatException e) {
        throw new RuntimeException("Failed to parse config " + name + ".", e);
      }
    }

    <T> T get(String name, Function<String, T> parser, T defaultValue) {
      Object tmp = config.get(name);
      try {
        return tmp != null ?
            parser.apply(tmp.toString()) : defaultValue;
      } catch (NumberFormatException e) {
        throw new RuntimeException("Failed to parse config " + name + ".", e);
      }
    }

    Object get(String name) {
      return config.get(name);
    }

    boolean containsKey(String name) {
      return config.containsKey(name);
    }

    boolean isEmpty() {
      return config.isEmpty();
    }

  }

  // general generators

  /**
   * <ul>
   * Options:
   * <li>len: string length, default 8</li>
   * </ul>
   */
  private static String genString(FieldConfig config) {
    int len = config.get("len", Integer::valueOf, 8);
    return RandomStringUtils.randomAlphabetic(len);
  }

  private static UUID genUUID(FieldConfig config) {
    return UUID.randomUUID();
  }

  private static ZonedDateTime genZonedDateTime(FieldConfig config) {
    return ZonedDateTime.now();
  }

  private static Date genDate(FieldConfig config) {
    return new Date();
  }

  /**
   * <ul>
   * Options:
   * </ul>
   */
  private static Boolean genBoolean(FieldConfig config) {
    return RandomUtils.nextBoolean();
  }

  /**
   * <ul>
   * Options:
   * <li>start: start from, default 0</li>
   * <li>end: end from, default 9</li>
   * </ul>
   */
  private static Integer genInteger(FieldConfig config) {
    int start = config.get("start", Integer::valueOf, 0);
    int end = config.get("end", Integer::valueOf, 9);
    return RandomUtils.nextInt(start, end);
  }

  /**
   * <ul>
   * Options:
   * <li>start: start from, default 0</li>
   * <li>end: end from, default 9</li>
   * </ul>
   */
  private static Long genLong(FieldConfig config) {
    int start = config.get("start", Integer::valueOf, 0);
    int end = config.get("end", Integer::valueOf, 9);
    return RandomUtils.nextLong(start, end);
  }

  /**
   * <ul>
   * Options:
   * <li>start: start from, default 0</li>
   * <li>end: end from, default 1</li>
   * </ul>
   */
  private static Double genDouble(FieldConfig config) {
    double start = config.get("start", Double::valueOf, 0D);
    double end = config.get("end", Double::valueOf, 1D);
    return RandomUtils.nextDouble(start, end);
  }

  /**
   * <ul>
   * Options:
   * <li>start: start from, default 0</li>
   * <li>end: end from, default 1</li>
   * </ul>
   */
  private static BigDecimal genBigDecimal(FieldConfig config) {
    return new BigDecimal(genDouble(config));
  }

  public static class GeneratorConfigBuilder {

    private Map<String, Map<String, Object>> config = new HashMap<>();

    private String selectedField;

    private GeneratorConfigBuilder() {
    }

    public static GeneratorConfigBuilder create() {
      return new GeneratorConfigBuilder();
    }

    private void checkIfFieldSelected() {
      if (selectedField == null) {
        throw new BuildGenerateConfigException(
            "No field selected, call selectField to select a field.");
      }
    }

    public GeneratorConfigBuilder selectField(String fieldName) {
      selectedField = fieldName;
      if (!config.containsKey(fieldName)) {
        config.put(fieldName, new HashMap<>());
      }
      return this;
    }

    public GeneratorConfigBuilder put(String configName, String configValue) {
      putConfig(configName, configValue);
      return this;
    }

    public GeneratorConfigBuilder put(String configName, Boolean configValue) {
      putConfig(configName, configValue);
      return this;
    }

    public GeneratorConfigBuilder put(String configName, Integer configValue) {
      putConfig(configName, configValue);
      return this;
    }

    public GeneratorConfigBuilder put(String configName, Double configValue) {
      putConfig(configName, configValue);
      return this;
    }

    private void putConfig(String configName, Object configValue) {
      checkIfFieldSelected();
      config.get(selectedField).put(configName, configValue);
    }

    public Map<String, Map<String, Object>> build() {
      return config;
    }

  }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
POJOGenerator(POJO代码生成器 v1.3.3) 本POJO代码生成器采用Java的Swing技术编码实现,是绿色免费工具,可以自由传播。 由于本工具的内部实现较烂,所以还请反编译高手手下留情,让我留几分颜面。^_^ 由于本人只用过Oracle、DB2、MySQL、MS SQL Server这四款数据库产品,所以制作 成exe可执行文件时只添入了这四款数据库的驱动支持。如果您需要使用这款工具从 其它数据库中生成POJO,那么您可以联系我(Email:CodingMouse@gmail.com), 我会添加其它数据库的驱动支持后通过电子邮件发送给您。 简单的使用说明: 1、先将压缩档解压到任意文件夹,必须保留配置文件cmsdk4j.cfg.xml和generator .cfg.xml与可执行文件POJOGenerator.exe在同一目录,否则无法运行。 2、可以预先在配置档cmsdk4j.cfg.xml中设定您的数据库服务器配置,配置档中已经 提供了默认的配置信息,您仅需在此基础上修改部分参数(如:IP地址、端口号、 用户名、密码、数据库名等),这些参数将作为生成器的预设数据库连接配置参数。 3、可以预先在配置档generator.cfg.xml中设定您的数据类型映射方案,配置档中已经 提供了MS SQL Server/MySQL/DB2和Oracle两种映射方案,当然,可能有不太完整的地方 ,您可以根据实际情况稍作修改即可。需要注意的一点是ref属性表示引用同一映射方案 的另一映射,这样您便可以简化同一映射数据类型的配置;而import属性是指定需要在 最终生成的源代码中作为类最开始的package类型导入声明部分的导入类型名称,因此, 这个名称是完整带包名的类名称,否则不能正确生成最终代码。配置档中提供的默认配 置如果不能满足你的需要,也可以自行根据实际情况进行修改。最后,需要大家注意的 一点就是由于最终生成的代码要调用包装类型的equals和hashCode方法,因此,配置的 数据类型必须是包装类型,如果用基本类型生成POJO代码是无法通过编译的。 4、所有配置档仅在工具启动初始读取一次并缓存到内存中,因此,如果您是在工具运行 时修改的配置档,请重新启动本工具以使新的配置生效。并且,所有配置档的XML结构均 不能修改,只能修改其节点间的文本值或属性值,以及添加新的标签组,否则会导致本 工具无法工作。选择“界面皮肤方案”后,默认会在当前目录生成名为skin.dat的文件, 这是一个Properties属性文件,用于保存您最后选择的皮肤名称,以便下次打开此工具 时加载您所选择的皮肤来渲染工具UI界面。 5、所有最终代码生成效果都可以在左边的代码预览区域中查看,可点击滑动箭头显示出 被隐藏的POJO代码卡片。点击“写入磁盘文件”按钮即可将POJO代码的Java源码文件写入 到指定文件夹中。POJO代码的equals方法重写完全符合《Core Java》所述规范,同时, 其中的hashCode方法重写则参考了Netbeans中JavaBean转换器的写法。为保障原有代码安 全,通常更好的做法是将最终代码生成后拷贝到您的项目对应文件夹中。最好不要直接指 向您的项目文件夹,因为本工具会直接覆盖掉指定目录中同名的文件。最终生成的代码文 件以.java为扩展名。 6、从1.3版开始生成POJO代码目录中可自动添加一个名为pojo.ntf.xml的POJO映射通 知档,其中,ID列名默认使用主键名称(若为复合主键则采用次序排首位的主键列名) ,而Oracle环境下的sequence对象名称则为“seq_表名_id”格式的默认名称,请根据 实际情况修改。该配置档用于CmSdk4j-Core框架的ORM映射,不需要则请不要勾选此项或 在生成后直接删除即可。 7、目前1.3.3版与1.3版差异不大,仅修改了POJO类名与成员变量名的大小写处理策略。 即目标数据库服务器为Oracle时,才将表名除首字母外全部小写处理成POJO类名,同理, 成员变量名也只在Oracle数据库情况下才全小写处理。其余数据库如:DB2、MySQL、 MS SQL Server则直接处理为除首字母大写外,其余全部保留原始大小写。其中,对于 表名的处理还直接去掉了空格符和下划线,并且若为Oracle数据库时,下划线亦作为首 字母大写的分隔标志,如:HRM_HUMAN_RESOURCE,最终生成POJO类名将直接去掉串中 的下划线,并以下划线作为首字母大写的起始,即:HrmHumanResource + POJO类名后缀。 同理,成员变量名的处理也是采用了相同的处理策略。最终处理效果详见生成写入到磁盘 的pojo.ntf.xml配置档。 8、此小工具一直均只写来自用,以便与自己的O/R Mapping简易版工具配套使用,目前 1.3.3这个版本已经能满足自己的需要,同时为了方便预览POJO代码生成的效果,特意添 加了语法着色功能,其着色色调搭配和关键字字典数据来源于EmEditor这款带语法着色的 纯文本编辑器,并且该色调搭配方案也被多款JS版本的语法着色器采用,色调可读性较高。 此小工具虽然GUI、功能这些都相对较弱,但自用已经足够。因此,后期可能就不再考虑 功能更新了,请见谅! 如果您有好的建议,请发送留言到作者博客:http://blog.csdn.net/CodingMouse 或发送邮件到:CodingMouse@gmail.com 本工具已经打包成exe可执行文件,便于在Window环境下运行,但仍需要你的机器上 安装至少1.6版本的jre环境(受打包工具的jre版本不兼容限制影响)。 By CodingMouse 2010年5月22日
POJOGenerator(POJO代码生成器 v1.2) 本POJO代码生成器采用Java的Swing技术编码实现,是绿色免费工具,可以自由传播。 由于本工具的内部实现较菜,所以还请反编译高手手下留情,让我留几分颜面。^_^ 作者本人只用过Oracle、MySQL、MS SQL Server这三款数据库产品,所以制作成exe 可执行文件时只添入了这三款数据库的驱动支持。如果您需要使用这款工具从其它 数据库中生成POJO,那么您可以联系我(Email:CodingMouse@gmail.com),我会 添加其它数据库的驱动支持后通过电子邮件发送给您。 简单的使用说明: 1、先将压缩档解压到任意文件夹。 2、可以预先在配置档cmsdk4j.cfg.xml中设定您的数据库服务器配置,配置档中已经 提供了默认的配置信息,您仅需在此基础上修改部分参数(如:IP地址、端口号、 用户名、密码、数据库名等),这些参数将作为生成器的预设数据库连接配置参数。 3、可以预先在配置档generator.cfg.xml中设定您的数据类型映射方案,配置档中已经 提供了MS SQL Server和Oracle两种映射方案,当然,可能有不太完整的地方,您可以 根据实际情况稍作修改即可。需要注意的一点是ref属性表示引用同一映射方案的另一 映射,这样您便可以简化同一映射数据类型的配置;而import属性是指定需要在最终 生成的源代码中作为类最开始的package类型导入声明部分的导入类型名称,因此,这 个名称是完整带包名的类名称,否则不能正确生成最终代码。配置档中提供的默认配置 如果不能满足你的需要,也可以自行根据实际情况进行修改。 4、所有配置档仅在工具启动初始读取一次并缓存到内存中,因此,如果您是在工具运行 时修改的配置档,请重新启动本工具以使新的配置生效。并且,所有配置档的XML结构均 不能修改,只能修改其节点间的文本值或属性值,否则会导致本工具无法工作。 5、所有最终代码生成效果都可以在左边的代码预览区域中查看和进行二次修改,点击 【写入磁盘文件】按钮生成到磁盘文件时将以代码预览区中的内容为准。当然,通常 更好的做法是将最终代码生成后拷贝到您的项目对应文件夹中。最好不要直接指向您的 项目文件夹,因为本工具会直接覆盖掉指定目录中同名的文件。最终生成的代码文件以 .java为扩展名。 如果您有好的建议,请发送留言到作者博客:http://blog.csdn.net/CodingMouse 或发送邮件到:CodingMouse@gmail.com 本工具已经打包成exe可执行文件,便于在Window环境下运行,但仍需要你的机器上 安装至少1.5版本的jre环境。 关联文章:http://blog.csdn.net/CodingMouse/archive/2009/07/13/4345782.aspx http://www.java2000.net/p17774 By CodingMouse 2009年7月14日
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值