Я прочитал много тем о сопоставлении с помощью JPA + Hibernate, но, попробовав несколько вещей, не могу получить ожидаемого результата.
Я объявил все свои однонаправленные отношения, так как не вижу необходимости двунаправленно их направлять
Мои объекты для отображения: У клиента есть Страна и список адресов.
@Table(name = "Client")
@Entity
public class Client
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
private Long id;
@OneToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
@JoinColumn(name = "country_id", unique = false, /*nullable = false,*/ insertable = true, updatable = false, foreignKey = @ForeignKey(name = "country_fk0"))
private Country country;
@OneToMany(cascade = { CascadeType.PERSIST }, orphanRemoval = true)
@JoinColumn(name = "address_id",/* nullable = false,*/ foreignKey = @ForeignKey(name = "address_fk0"))
private List<Address> address;
//GETTERS / SETTERS
}
затем я оценю клиента и сохраню его в новой таблице ClientProcessed, которая будет ссылаться на объекты Addresses и Country, хранящиеся в моем объекте Client.
@Table(name = "ProcessedClient")
@Entity
public class ProcessedClient
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
private Long id;
@OneToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
@JoinColumn(name = "client_evaluation_id", unique = false, /*nullable = false,*/ insertable = true, updatable = false, foreignKey = @ForeignKey(name = "evaluation_fk0"))
private ClientEvaluation evaluation;
@OneToOne(cascade = { CascadeType.MERGE })
@JoinColumn(name = "country_id", unique = false, /*nullable = false,*/, foreignKey = @ForeignKey(name = "country_fk1"))
private Country country;
@OneToMany(cascade = { CascadeType.MERGE}, orphanRemoval = true)
@JoinColumn(name = "address_id",/* nullable = false,*/ foreignKey = @ForeignKey(name = "address_fk2"))
private List<Address> addresses;
//GETTERS / SETTERS
}
Итак, когда я это делаю:
Country country = new Country();
country.setId(1l); // (DB ID)
// I do the same with addresses
ProcessedClient processedClient = new ProcessedClient();
processedClient.setAddresses(addresses);
processedClient.setCountry(country);
this.getDao().save(processedClient);
Результат:
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing
Спасибо
Но в этом случае мой объект представлен в базе данных. Это происходит потому, что у вас есть коллекция в вашей сущности, и в этой коллекции есть один или несколько элементов, которых нет в базе данных. Указав вышеуказанные параметры, вы указываете hibernate сохранять их в базе данных при сохранении их родителя.




Из документации:
Hibernate определяет и поддерживает следующие состояния объекта:
Вы должны загрузить страну из базы данных по идентификатору, а затем установить его в ProcessedClient.
Возможный дубликат объект ссылается на несохраненный переходный экземпляр — сохраните переходный экземпляр перед очисткой