#java #hibernate #inheritance #jpa #toplink
#java #переход в спящий режим #наследование #jpa #toplink
Вопрос:
Привет, я новичок в JPA, и у меня возникли проблемы с пониманием того, как он обрабатывает наследование.
У меня есть конкретная проблема, которую мне нужно решить без изменения схемы БД, но если вы не можете найти решение, я был бы признателен за предложения по решению с другой схемой БД (приветствуются решения Hibernate / TopLink).
Если я был неясен или вам нужна дополнительная информация, пожалуйста, скажите мне об этом. Заранее спасибо!
У меня есть эта база данных:
TABLE Fruit
Id Varchar (10) Primary Key
size Varchar (10)
fruit_type Varchar(10)
TABLE Apple
Id Varchar (10) Primary Key Foreign Key references Fruit.Id
Apple_Property Varchar(10)
Пока что мои объекты выглядят следующим образом :
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="fruit_type", discriminatorType=DiscriminatorType.Char)
@DiscriminatorValue(value="fruit")
public class Fruit implements Serializable {
@Id
protected String Id;
protected String size;
}
@Entity
@DiscriminatorValue(value="apple")
//@PrimaryKeyJoinColumn(name="Id" , referencedColumnName="Id")
public class Apple extends Fruit implements Serializable {
private String Apple_Property;
}
В настоящее время я могу сохранять объекты Fruit без проблем..
Объекты Apple сохраняются только тогда, когда их объект Fruit еще не был сохранен.
Если я попытаюсь сохранить объект apple с уже сохраненным объектом Fruit :
Fruit fruit1 = new Fruit("1", "Small");
Apple apple1 = new Apple(fruit1, "red");
provider.create(fruit1);
provider.create(apple1);
Я получу сообщение об ошибке, поскольку JPA пытается создать новую строку в таблице Fruit с Id = «1»
которое уже существует.
..
Ответ №1:
При использовании JPA для сохранения дочернего объекта (т.е. provider.create(apple1)
в вашем случае) в дочернюю таблицу и все ее родительские таблицы будет вставлена запись. Таким образом, provider.create(apple1)
будет вставлена запись в the Fruit и запись в таблицу Apple.
В вашем примере, если вы хотите сохранить только объект Apple, достаточно просто вызвать provider.create(apple1)
. Ссылка на fruit также будет сохранена внутри объекта Apple.
Кстати, я предлагаю, чтобы PK в таблице Fruit имел числовой тип и использовался @GeneratedValue
для обозначения поля ID компонента Fruit. Таким образом, вы можете позволить базе данных генерировать идентификатор для вас, и вам больше не нужно устанавливать его явно в коде Java, чтобы избежать этой ошибки «Идентификатор уже существует» из-за установки уже существующего идентификатора в коде Java.
Комментарии:
1. Спасибо за ваш ответ! Но .. мне нужно иметь возможность сохранять fruit1 и позже создавать объект apple из этого fruit1… Но при этом я получаю дублирующуюся ошибку первичного ключа .. сохраняющийся fruit1 позже запишет в таблицу значения Fruit (1, Small, Fruit), при сохранении apple1 он вставляет значения (1, red) в таблицу Apple, но вылетает при попытке снова вставить значения (1, Small, Fruit) в таблицу Fruit
2. При первом сохранении fruit1 вы должны сохранить его как объект apple вместо объекта fruit . Таким образом, записи с присвоенным вами идентификатором будут вставлены как в таблицу fruit, так и в таблицу apple . Затем, после того как вы узнаете свойства объекта Apple позже, вы извлекаете объект Apple из базы данных, используя идентификатор, и обновляете его значение.
Ответ №2:
Я думаю, что это работает именно так, как задумано. Когда вы используете объединенное наследование и сохраняете объект apple, JPA автоматически вставит его как в таблицы apple, так и в таблицы fruit. Вам не нужно моделировать дополнительное отношение или объединенный столбец в ваших классах сущностей.
Ответ №3:
Вы пытаетесь использовать концепцию наследования Java при создании таблиц db, что в данном случае несколько невозможно. Я мог бы придумать другой подход к этой проблеме. Есть таблица fruit_type и fruit. fruit_type(идентификатор, имя_типа, описание) fruit(идентификатор, имя, type_id, описание) здесь type_id будет внешним ключом.
Комментарии:
1. Это возможно в JPA. Смотрите : wiki.eclipse.org/EclipseLink/Examples/JPA /…
Ответ №4:
У меня такая же проблема, и пока единственным способом, который я нашел, было запросить родительский элемент и создать дочерний элемент с помощью parent. Затем удалите родительский элемент и воссоздайте обе записи заново.