【问题标题】:Mapping a Collection of Enums to a single varchar column将枚举集合映射到单个 varchar 列
【发布时间】:2012-09-04 11:10:23
【问题描述】:

在休眠中,我需要将枚举集合映射到单个 varchar 列(例如,作为逗号分隔的枚举值列表)。

【问题讨论】:

    标签: java hibernate collections enums mapping


    【解决方案1】:

    您可以创建一个 Hibernate UserType,在其中将值设置为逗号分隔的字符串:

     public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException {
        try {
            if (null == value) {
                st.setNull(index, Types.VARCHAR);
            } else {
                st.setString(index, toCommaSeparated((Set<Enum>) value));
            }
        } catch (Exception e) {
            throw new HibernateException(String.format("Exception while stringifing '%s'", value), e);
        }
    
    }
    
    private String toCommaSeparated(Set<Enum> inputSet) {
        StringBuilder sb = new StringBuilder();
        String delim = "";
        for (Enum current : inputSet) {
            sb.append(delim).append(current.name());
            delim = ",";
        }
        return sb.toString();
    }
    

    你得到它作为一个 EnumSet:

        @Override
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        String name = rs.getString(names[0]);
        if (rs.wasNull()) {
            return null;
        }
    
        try {
            Set<Enum<?>> retSet = EnumSet.noneOf(enumClass);
            if (StringUtils.isNotBlank(name)) {
                String[] values = name.split(",");
                for (String value : values) {
                    Enum<?> current = getEnumValueFor(value);
                    if (current != null) {
                        retSet.add(current);
                    }
                }
            }
            return retSet;
        } catch (Exception e) {
            throw new HibernateException("Exception getting object from comma separated string", e);
        }
    }
    
    private Enum<?> getEnumValueFor(String name) {
        for (Enum<?> current : enumClass.getEnumConstants()) {
            if (current.name().equals(name)) {
                return current;
            }
        }
        return null;
    }
    

    这个实现只是为了给你一个想法,它当然可以改进或适应你的需要。您还可以找到大量关于如何创建自己的 UserType 并可能使用您要存储的 Enum 类对其进行参数化的教程。

    【讨论】:

      【解决方案2】:

      我真的不会这样做,因为它使查询您的数据变得不可能。

      如果你真的想这样做,那么只需将集合转换为 setter 中的字符串,然后将字符串转换为枚举集合到 getter。使用番石榴:

      private String fooValues;
      
      public EnumSet<Foo> getFoos() {
          EnumSet<Foo> result = EnumSet.noneOf(Foo.class);
          for (String fooAsString : Splitter.on(',').split(fooValues)) {
              result.add(Foo.valueOf(fooAsString);
          }
          return result;
      }
      
      public void setFoos(EnumSet<Foo> foos) {
          this.fooValues = Joiner.on(",").join(foos);
      }
      

      【讨论】:

      • thnks,但我从 hibernate 中寻找一个可以执行此转换的工具。
      • 在您的解决方案中,字符串拆分在每个 getter 调用中完成。尝试优化性能会导致在 Set 属性和 String 属性之间同步代码,所有这些都会使代码变脏。
      • 你不会找到一个,因为将一组值存储在单个列中非常难看。将其存储在单独的表中,一切都将由 Hibernate 完成。
      • 我倾向于这种丑陋的解决方案,以避免影响性能的额外连接。
      猜你喜欢
      • 2012-04-08
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-14
      • 1970-01-01
      相关资源
      最近更新 更多