Отображение нескольких строк для каждого элемента объекта в Hibernate - PullRequest
2 голосов
/ 27 августа 2010

Я сталкиваюсь с неординарным дизайном, и я не совсем уверен, как с этим справиться. Таблица, которую я пытаюсь отобразить, выглядит следующим образом:

TABLE example {
    ID INT,
    CATEGORY VARCHAR,
    PROPERTY VARCHAR,
    VALUE VARCHAR);

Один идентификатор может иметь несколько строк (очевидно, не первичный ключ). В качестве примера это может выглядеть так:

# ID  CATEGORY     PROPERTY VALUE
  1   general_info name     order 1
  1   general_info date     1/1/2009
  ...

У каждого идентификатора может быть несколько разных категорий. Имена свойств уникальны для любой заданной комбинации (идентификатор, категория).

(РЕДАКТИРОВАТЬ) Поле ID является внешним ключом для объектов в другой таблице. Мне нужно иметь возможность получить от этих объектов различные свойства, хранящиеся в этой таблице, используя только поле идентификатора. Если нужно использовать составной ключ, как мне связать его?

(EDIT2) Я также думаю, что деталь, которую вы здесь упускаете, заключается в том, что все данные с одинаковым идентификатором в первом столбце концептуально принадлежат одному и тому же объекту. Мне не нужен отдельный экземпляр для каждой комбинации (ID, CATEGORY).

Очевидно, это не очень нормализовано. В худшем случае я создал несколько дополнительных таблиц, которые нормализуются и копируют все, но мне было интересно, кто-нибудь мог бы предложить разумный способ напрямую передать эту информацию в объекты с поддержкой hibernate? При необходимости в какой-то сумке свойств String.

Кстати, я использую hibernate-аннотации.

Ответы [ 2 ]

2 голосов
/ 27 августа 2010

Используйте составной ключ с ID, КАТЕГОРИЕЙ и ИМУЩЕСТВОМ.См. Несколько ключей в спящем режиме как? и JPA - Проблема проектирования сущностей для примеров того, как реализовать это (ключ @EmbeddedId!)

1 голос
/ 29 августа 2010

Поскольку идентификатор является внешним ключом для другой таблицы (давайте назовем эту таблицу «контейнером»), его можно отобразить как карту с составным ключом.

Пример:

public class Container {
    private int id;
    private Map<Key,String> values = new HashMap<Key,String>();

    public String getValue(String category, String property) {
        return values.get(new Key(category, property));
    }

    public void setValue(String category, String property, String value) {
        values.put(new Key(category, property), value);
    }

    public static class Key {
        private String category;
        private String property;

        public Key(String cat, String prop) {
            category = cat;
            property = prop;
        }

        public String getCategory() {
            return category;
        }

        public String getProperty() {
            return property;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof Key)) {
                return false;
            }
            Key k = (Key)obj;
            return category.equals(k.category) && property.equals(k.property);
        }

        @Override
        public int hashCode() {
            return 37*category.hashCode() + property.hashCode();
        }
    }
}

Отображение:

<class name="Container" table="container">
    <id column="ID" name="id">
        <generator class="native"/>
    </id>
    <map cascade="all-delete-orphan" name="values" table="example">
        <key column="ID"/>
        <composite-map-key class="Container$Key">
            <key-property name="category" type="string" column="CATEGORY"/>
            <key-property name="property" type="string" column="PROPERTY"/>
        </composite-map-key>
        <element type="string" column="VALUE"/>
    </map>
</class>
...