2013-03-11 33 views
0

“动态枚举”是一个矛盾,就像“静态变量”? ;-)Spring中的动态枚举,或者如何让Spring远离构造函数?

我只在春季浸泡的时间很短,我怀疑我没有想到春天般​​呢。我想有一个类型安全的动态枚举。我已经使用这种模式来处理事件或错误代码,您希望允许后续子类扩展枚举。由于“枚举”不能被扩展,你只剩下一个枚举模式类。例如(精简):

public class EventType { 

    private String name;  

    private static HashMap<String, EventType> cache 
        = new HashMap<String, EventType>(); 

    protected EventType(String name) { 
     if (cache.containsKey(name)) { 
      throw new RuntimeException("EventType '" + name + "' already exists!"); 
     } else { 
      this.name = name; 
      cache.put(name, this); 
     } 
    } 

    public static AuditEventType parse(String name) { 
     return cache.get(name); 
    } 

    public static final EventType EVENT_START = new AuditEventType("Start"); 
    public static final EventType EVENT_END = new AuditEventType("End"); 
    public static final EventType EVENT_FAIL = new AuditEventType("Fail"); 
} 

的问题,开始的时候我增加了Spring的组合。由于它只是一个字符串,我已经将EventType注释为“@Embeddable”,并且使用它的类将该成员注释为“@Embedded”。这似乎工作很好,直到查询使用queryDSL-jpa的时间。 DSL会尝试将数据库文本转换为EventType,然后与字符串的类型不匹配。也就是说,我不能说:WHERE EventType = "Start"。通过让这样的字段类将其存储为字符串,并将其解析为getter中的EventType对象,我解决了这个问题(不是很好)。就JPA而言,现在它只是一个普通的字符串。

现在我正在与服务API的问题。我有一个EventType参数的方法。问题是JsonRpcServer类试图通过实例化字符串到一个EventType。这当然会抛出“已经存在!”例外。

我也许可以解决@JsonTypeResolver(这我读了关于现在)这个第二个问题。但所有这些诡计都是错误的。这一定是一个常见问题,必须有更好的解决方案。在Spring中处理这些类的正确方法是什么? (它不是一个bean,真的,并且有一个受保护的构造函数)。

(我要离开了一些细节了解我们的代码使用一些专有库,而这可能不会让我喜欢采取“哦,你应该用‘X’来代替。”谢谢你的理解的答案。)

回答

1

对于弹簧侧看一看的conversionService。这让您注册自定义转换器。所以你应该能够注册你的EventTypeToStringConverter和StringToEventTypeConverter。他们将拥有“完整”的控制权来解析/来自你的事件类型。

对于休眠方面,它可能是使用一个特定的用户类型为你的事件类型,因为Hibernate能够存储和读取它作为一个列值的解决方案。 (这是我期望你需要的) 我有一个类似的需求,每个实体的状态,我不想作为一个实体本身建模。 我没有设法直接在查询中使用字符串参数,但有很多接口可能会实现,最有可能的是允许对参数进行字符串识别。

+0

感谢您的建议,马丁。 'conversionService'听起来很有前途。至于UserType,是的,我已经这样做了(再次感谢你,StackOverflow!)最后,我需要做的就是添加'@JsonDeserize(using = ...)'。这工作很好,以保持JSON-RCP转换免于试图重新实例化我的静态实例。一旦我有机会,我会试用'converionService'并更新线程。再次感谢! – Didjit 2013-03-13 00:08:47