0

Is "Dynamic enumerations" an oxymoron, like "static variables"? ;-)

I've only been soaking in Spring for a short time, and I suspect I'm not thinking Spring-like yet. I would like to have a type-safe, dynamic enumeration. I've used this pattern for things like events or error codes where you want to allow subsequent sub-classes to expand the enumeration. Since "enum" can't be extended you're left with an enumeration pattern class. For example (stripped down):

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");
}

The problems start when I add Spring to the mix. Since it's only a string, I've annotated EventType as "@Embeddable", and classes that use it annotate that member as "@Embedded". This seemed to work great until it came time for querying using queryDSL-jpa. DSL would try to convert the DB text to an EventType, which then would have a type mismatch with strings. That is, I couldn't say: WHERE EventType = "Start". I got around this (not elegantly) by having the class with such a field store it as a String, and parse it to an EventType object in the getter. So now it's just a plain ol' string as far as JPA is concerned.

Now I'm running into an issue with the service API. I have a method with an EventType parameter. The problem is that the JsonRpcServer class is trying to convert the String to an EventType by instantiating it. This of course throws an "already exists!" exception.

I can probably solve this second issue with @JsonTypeResolver (which I'm reading up on now). But all of these shenanigans feel wrong. This must be a common issue and there's got to be a better solution. What's the proper way of handling such classes in Spring? (where it's not a bean, really, and has a protected constructor).

(I'm leaving out some specifics about some proprietary libraries our code uses, and which might not let me adopt an answer like "Oh, you should be using 'X' instead." Thanks for understanding.)

4

1 回答 1

1

对于 Spring 方面,请查看 conversionService。这使您可以注册自定义转换器。所以你应该能够注册你的 EventTypeToStringConverter 和 StringToEventTypeConverter。他们将拥有“完全”控制权来解决您的事件类型。

对于 Hibernate 而言,为 EventType 使用特定的 UserType 可能是一种解决方案,因此 Hibernate 能够将其作为列值存储和读取。(这是我希望您需要的)我对每个实体都有类似的要求,我不想将其建模为实体本身。我还没有设法直接在查询中使用字符串参数,但是有很多接口可以实现,很可能有一个接口允许对参数进行字符串识别。

于 2013-03-12T06:29:05.790 回答