【问题标题】:Initial data on JPA repositoriesJPA 存储库上的初始数据
【发布时间】:2014-06-07 13:08:50
【问题描述】:

我正在寻找一种方便的方式来为我的应用程序提供初始数据。目前我已经实现了一个基于 Spring Data JPA 的项目,这是我所有数据库相关操作的基础。

例子:

我有一个实体Role,它可以分配给实体User。在一个干净的应用程序启动时,我想直接提供一些默认角色(例如管理员、经理等)。

最好的

【问题讨论】:

    标签: spring jpa spring-data


    【解决方案1】:

    我建立了一个随机数据工厂:

    public class RandomDataFactory {
    
        private static final String UNGENERATED_VALUE_MARKER = "UNGENERATED_VALUE_MARKER";
    
        private static void randomlyPopulateFields(Object object) {
            new RandomValueFieldPopulator().populate(object);
        }
    
        /**
         * Instantiates a single object with random data
         */
        public static <T> T getSingle(Class<T> clazz) throws IllegalAccessException, InstantiationException {
            T object = clazz.newInstance();
            randomlyPopulateFields(object);
            return object;
        }
    
        /**
         * Returns an unmodifiable list of specified type objects with random data
         *
         * @param clazz     the myPojo.class to be instantiated with random data
         * @param maxLength the length of list to be returned
         */
        public static <T> List<T> getList(Class<T> clazz, int maxLength) throws IllegalAccessException, InstantiationException {
            List<T> list = new ArrayList<T>(maxLength);
            for (int i = 0; i < maxLength; i++) {
                T object = clazz.newInstance();
                randomlyPopulateFields(object);
                list.add(i, object);
            }
            return Collections.unmodifiableList(list);
        }
    
        /**
         * Returns a unmodifiable list of specified type T objects with random data
         * <p>List length will be 3</p>
         *
         * @param clazz the myPojo.class to be instantiated with random data
         */
        public static <T> List<T> getList(Class<T> clazz) throws InstantiationException, IllegalAccessException {
            return getList(clazz, 3);
        }
    
        public static <T> T getPrimitive(Class<T> clazz) {
            return (T) RandomValueFieldPopulator.generateRandomValue(clazz);
        }
    
        public static <T> List<T> getPrimitiveList(Class<T> clazz) {
            return getPrimitiveList(clazz, 3);
        }
    
        public static <T> List<T> getPrimitiveList(Class<T> clazz, int length) {
            List<T> randoms = new ArrayList<T>(length);
            for (int i = 0; i < length; i++) {
                randoms.add(getPrimitive(clazz));
            }
            return randoms;
        }
    
        private static class RandomValueFieldPopulator {
            public static Object generateRandomValue(Class<?> fieldType) {
                Random random = new Random();
                  if (fieldType.equals(String.class)) {
                    return UUID.randomUUID().toString();
                } else if (Date.class.isAssignableFrom(fieldType)) {
                    return new Date(System.currentTimeMillis() - random.nextInt());
                } else if (LocalDate.class.isAssignableFrom(fieldType)) {
                    Date date = new Date(System.currentTimeMillis() - random.nextInt());
                    return new LocalDate(date);
                } else if (fieldType.equals(Character.class) || fieldType.equals(Character.TYPE)) {
                    return (char) (random.nextInt(26) + 'a');
                } else if (fieldType.equals(Integer.TYPE) || fieldType.equals(Integer.class)) {
                    return random.nextInt();
                } else if (fieldType.equals(Short.TYPE) || fieldType.equals(Short.class)) {
                    return (short) random.nextInt();
                } else if (fieldType.equals(Long.TYPE) || fieldType.equals(Long.class)) {
                    return random.nextLong();
                } else if (fieldType.equals(Float.TYPE) || fieldType.equals(Float.class)) {
                    return random.nextFloat();
                } else if (fieldType.equals(Double.TYPE)) {
                    return random.nextInt(); //if double is used, jsonPath uses bigdecimal to convert back
                } else if (fieldType.equals(Double.class)) {
                    return random.nextDouble(); //if double is used, jsonPath uses bigdecimal to convert back
                } else if (fieldType.equals(Boolean.TYPE) || fieldType.equals(Boolean.class)) {
                    return random.nextBoolean();
                } else if (fieldType.equals(BigDecimal.class)) {
                    return new BigDecimal(random.nextFloat());
                } else if (Enum.class.isAssignableFrom(fieldType)) {
                    Object[] enumValues = fieldType.getEnumConstants();
                    return enumValues[random.nextInt(enumValues.length)];
                } else if (Number.class.isAssignableFrom(fieldType)) {
                    return random.nextInt(Byte.MAX_VALUE) + 1;
                } else {
                    return UNGENERATED_VALUE_MARKER;
                }
    
            public void populate(Object object) {
                ReflectionUtils.doWithFields(object.getClass(), new RandomValueFieldSetterCallback(object));
            }
    
            private static class RandomValueFieldSetterCallback implements ReflectionUtils.FieldCallback {
                private final Object targetObject;
    
                public RandomValueFieldSetterCallback(Object targetObject) {
                    this.targetObject = targetObject;
                }
    
                @Override
                public void doWith(Field field) throws IllegalAccessException {
                    Class<?> fieldType = field.getType();
                    if (!Modifier.isFinal(field.getModifiers())) {
                        Object value = generateRandomValue(fieldType);
                        if (!value.equals(UNGENERATED_VALUE_MARKER)) {
                            ReflectionUtils.makeAccessible(field);
                            field.set(targetObject, value);
                        }
                    }
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      查看内存中的 H2 数据库。

      http://www.h2database.com/html/main.html

      Maven 依赖

      <!-- H2 Database -->
      <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <version>1.4.178</version>
      </dependency>
      

      Spring Java 配置入口

      @Bean
      public DataSource dataSource() {
          System.out.println("**** USING H2 DATABASE ****");
          EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
          return builder.setType(EmbeddedDatabaseType.H2).addScript("/schema.sql").build();
      }
      

      您可以使用 .addscript() 在上述代码中使用 SQL 脚本创建/加载 H2 数据库。

      【讨论】:

        【解决方案3】:

        如果你将它用于单元测试,并且需要不同的状态来进行不同的测试,那么

        1. 有一个http://dbunit.sourceforge.net/

        2. 专门针对 Spring 有 http://springtestdbunit.github.io/spring-test-dbunit/

        如果您只需要初始化一次并使用 EmbeddedDatabaseBuilder 进行测试,那么正如 Brandon 所说,您可以使用 EmbeddedDatabaseBuilder。

        @Bean
        public DataSource dataSource() {
            EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
            return builder.setType(EmbeddedDatabaseType.H2).addScript("/schema.sql").build();
        }
        

        如果你希望它在应用程序启动时被初始化,你可以在你的配置bean中添加@PostConstruct函数,它会在配置bean创建后被初始化。

        @PostConstruct
        public void initializeDB() {
        }
        

        【讨论】:

          猜你喜欢
          • 2018-07-27
          • 2017-05-26
          • 2017-04-06
          • 2016-02-02
          • 1970-01-01
          • 2014-05-03
          • 2019-12-22
          • 1970-01-01
          • 2014-04-11
          相关资源
          最近更新 更多