Подтвердить что ты не робот

Объект JPA без идентификатора

У меня есть база данных со следующей структурой:

CREATE TABLE entity (
    id SERIAL,
    name VARCHAR(255),
    PRIMARY KEY (id)
);

CREATE TABLE entity_property (
    entity_id SERIAL,
    name VARCHAR(255),
    value TEXT
);

Когда я пытаюсь создать класс EntityProperty

@Entity
@Table(name="entity_property")
public class EntityProperty {

    private String name;
    private String value;

    @Column(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Column(name="value", nullable=true, length=255)
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

У меня есть исключение:

org.hibernate.AnnotationException: No identifier specified for entity: package.EntityProperty

Я знаю, что сущности JPA должны иметь первичный ключ, но я не могу изменить структуру базы данных по причинам, не зависящим от меня. Возможно ли создать объекты JPA (Hibernate), которые будут работать с структурой базы данных следующим образом?

4b9b3361

Ответ 1

Я думаю, ваш entity_property имеет составной ключ (entity_id, name), где entity_id является внешним ключом для entity. Если это так, вы можете отобразить его следующим образом:

@Embeddable
public class EntityPropertyPK {
    @Column(name = "name")
    private String name;

    @ManyToOne
    @JoinColumn(name = "entity_id")
    private Entity entity;

    ...
}

@Entity 
@Table(name="entity_property") 
public class EntityProperty { 
    @EmbeddedId
    private EntityPropertyPK id;

    @Column(name = "value")
    private String value; 

    ...
}

Ответ 2

Я знаю, что сущности JPA должны иметь первичный ключ, но я не могу изменить структуру базы данных по причинам, не зависящим от меня.

Точнее, объект JPA должен иметь определенный Id. Но JPA Id необязательно должен отображаться в первичном ключе таблицы (и JPA может каким-то образом иметь дело с таблицей без первичного ключа или уникального ограничения).

Возможно ли создать объекты JPA (Hibernate), которые будут работать с структурой базы данных, как это?

Если у вас есть столбец или набор столбцов в таблице, которые делают уникальное значение, вы можете использовать этот уникальный набор столбцов в качестве Id в JPA.

Если в вашей таблице нет уникальных столбцов, вы можете использовать все столбцы как Id.

И если ваша таблица имеет некоторый идентификатор, но ваша сущность не делает этого, сделайте его Embeddable.

Ответ 3

См. книгу Persistence Java: Идентификация и секвенирование

Соответствующей частью вашего вопроса является No Primary Key section:

Иногда ваш объект или таблица не имеют первичного ключа. Лучшее решение в этом случае обычно добавляется сгенерированный идентификатор к объекту и Таблица. Если у вас нет этой опции, иногда есть столбец или набор столбцов в таблице, которые составляют уникальное значение. Вы можете использовать этот уникальный набор столбцов как ваш идентификатор в JPA. JPA Idне всегда должен соответствовать первичному ключу таблицы базы данных ограничение, а также не является первичным ключом или требуемым уникальным ограничением.

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

Если ваш объект не имеет идентификатора, но его "таблица", это нормально. Сделать объект объектом Embeddable, встраиваемыми объектами не имеют идентификаторов. Вам понадобится Entity, который содержит это Embeddable, чтобы продолжить и запросить его.

Ответ 4

Я думаю, вы можете использовать @CollectionOfElements (для hibernate/jpa 1)/@ElementCollection (jpa 2), чтобы сопоставить коллекцию "свойств объекта" с List в entity.

Вы можете создать тип EntityProperty и аннотировать его с помощью @Embeddable

Ответ 5

Если между сущностью и entity_property существует одно к одному, вы можете использовать entity_id в качестве идентификатора.