Динамические перечисления в Spring, или как сохранить Spring от конструкторов?

Является ли "динамическое перечисление" оксюмороном, как "статические переменные"?;-)

Я только в течение короткого времени впитывал весну, и я подозреваю, что я еще не думаю о Spring. Я хотел бы иметь безопасное для типов динамическое перечисление. Я использовал этот шаблон для таких вещей, как события или коды ошибок, где вы хотите разрешить последующим подклассам расширять перечисление. Поскольку "enum" не может быть расширен, у вас остается класс шаблона перечисления. Например (урезанный):

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", Я справился с этим (не элегантно), сохранив класс с таким полем для хранения его как String и проанализировав его с объектом EventType в получателе. Так что теперь это просто старая строка в отношении JPA.

Теперь я столкнулся с проблемой с сервисным API. У меня есть метод с параметром EventType. Проблема в том, что класс JsonRpcServer пытается преобразовать String в EventType, создав его экземпляр. Это, конечно, бросает "уже существует!" исключение.

Я, вероятно, могу решить эту вторую проблему с @JsonTypeResolver (о которой я сейчас читаю). Но все эти махинации чувствуют себя не так. Это должно быть общей проблемой, и должно быть лучшее решение. Как правильно обращаться с такими классами в Spring? (где это не bean-компонент, действительно, и имеет защищенный конструктор).

(Я опускаю некоторые подробности о некоторых проприетарных библиотеках, которые использует наш код, и которые могут не позволить мне принять ответ типа "О, вы должны вместо этого использовать" X ". Спасибо за понимание".)

1 ответ

Для стороны Spring взгляните на ConversionService. Это позволяет вам регистрировать пользовательские конвертеры. Таким образом, вы должны иметь возможность зарегистрировать свой EventTypeToStringConverter и StringToEventTypeConverter. Они будут иметь "полный" контроль для разрешения от / к вашему типу события.

Для стороны Hibernate может быть решение использовать определенный UserType для вашего EventType, чтобы Hibernate мог сохранять и читать его как значение столбца. (это то, что, как я ожидаю, вам нужно) У меня было похожее требование со статусом для каждой сущности, который я не хотел моделировать как саму сущность. Мне пока не удавалось напрямую использовать строковый параметр в запросе, но существует множество интерфейсов, которые вы могли бы реализовать, скорее всего, есть такой, который позволяет распознавать строки для параметров.

Другие вопросы по тегам