У меня есть следующие виды классов для, в спящем режиме иерархия объекта. Я пытаюсь иметь два бетона sub классы Sub1Class
и Sub2Class
. Они разделяются столбцом различителя (field
) это определяется в MappedSuperClass
. Существует абстрактный класс объекта EntitySuperClass
на который ссылаются другие объекты. Другие объекты не должны заботиться, ссылаются ли они на самом деле Sub1Class
или Sub2Class
.
Это это на самом деле возможное? В настоящее время я получаю эту ошибку (потому что определение столбца наследовано дважды в Sub1Class и в EntitySuperClass):
Repeated column in mapping for entity: my.package.Sub1Class column: field (should be mapped with insert="false" update="false")
Если я добавляю @MappedSuperClass
кому: EntitySuperClass
, затем я добираюсь, ошибка утверждения от будьте в спящем режиме: этому не нравится, если классом является и Объект и отображенный суперкласс. Если я удаляю @Entity
от EntitySuperClass
, класс больше не является объектом и не может быть сослан от других объектов:
MappedSuperClass
часть внешнего пакета, поэтому если возможный он не должен быть изменен.
Мои классы:
@MappedSuperclass
public class MappedSuperClass {
private static final String ID_SEQ = "dummy_id_seq";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = ID_SEQ)
@GenericGenerator(name=ID_SEQ, strategy="sequence")
@Column(name = "id", unique = true, nullable = false, insertable = true, updatable = false)
private Integer id;
@Column(name="field", nullable=false, length=8)
private String field;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
}
@Entity
@Table(name = "ACTOR")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="field", discriminatorType=DiscriminatorType.STRING)
abstract public class EntitySuperClass extends MappedSuperClass {
@Column(name="description", nullable=false, length=8)
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
@Entity
@DiscriminatorValue("sub1")
public class Sub1Class extends EntitySuperClass {
}
@Entity
@DiscriminatorValue("sub2")
public class Sub2Class extends EntitySuperClass {
}
@Entity
public class ReferencingEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
@Column
private Integer value;
@ManyToOne
private EntitySuperClass entitySuperClass;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public EntitySuperClass getEntitySuperClass() {
return entitySuperClass;
}
public void setEntitySuperClass(EntitySuperClass entitySuperClass) {
this.entitySuperClass = entitySuperClass;
}
}
В моем проекте это делается так:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "field", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("dummy")
public class EntitySuperClass {
// here definitions go
// but don't define discriminator column here
}
@Entity
@DiscriminatorValue(value="sub1")
public class Sub1Class extends EntitySuperClass {
// here definitions go
}
И работает. Я думаю, ваша проблема в том, что вы без нужды определяете поле дискриминатора в своем определении суперкласса. Удалите его, и он будет работать.
Чтобы использовать столбец дискриминатора как обычное свойство, вы должны сделать это свойство доступным только для чтения с помощью insertable = false, обновляемый = false
. Поскольку вы не можете изменить MappedSuperClass
, вам необходимо использовать @AttributeOverride
:
@Entity
@Table(name = "ACTOR")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="field", discriminatorType=DiscriminatorType.STRING)
@AttributeOverride(name = "field",
column = @Column(name="field", nullable=false, length=8,
insertable = false, updatable = false))
abstract public class EntitySuperClass extends MappedSuperClass {
...
}
Вы можете отобразить столбец базы данных только один раз как поле для чтения-записи (поле, которое имеет insertable=true
и/или updatable=true
) и любое количество раз как поле только для чтения (insertable=false
и updatable=false
). Использование колонки как @DiscriminatorColumn
считается отображением чтение-запись, поэтому вы не можете иметь дополнительные отображения чтение-запись.
Hibernate будет устанавливать значение, указанное в @DiscriminatorColumn
за кулисами, основываясь на конкретном экземпляре класса. Если бы вы могли изменить это поле, это позволило бы модифицировать поле @DiscriminatorColumn
так, чтобы ваш подкласс и значение в поле могли не совпадать.