#java #hibernate #jpa #persistence
#java #спящий режим #jpa #постоянство
Вопрос:
Я получил эти 2 объекта:
@javax.persistence.Entity
public class Book {
@javax.persistence.EmbeddedId
private BookPK id;
private String title;
@javax.persistence.ManyToOne(fetch = javax.persistence.FetchType.LAZY)
@javax.persistence.JoinColumns({
@javax.persistence.JoinColumn(name = "LNGCOD", referencedColumnName = "LNGCOD"),
@javax.persistence.JoinColumn(name = "LIBCOD", referencedColumnName = "LIBCOD") })
private Language language;
}
@javax.persistence.Entity
public class Language {
@javax.persistence.EmbeddedId
private LanguagePK id;
private String name;
}
с составными ПК:
@Embeddable
public class BookPK implements Serializable {
private Integer bookcod;
private Integer libcod;
}
@Embeddable
public class LanguagePK implements Serializable {
private Integer lngcod;
private Integer libcod;
}
Если я пытаюсь создать новую книгу и сохранить ее, я получаю исключение, сообщающее мне, что libcod найден дважды в инструкции insert («Столбец ‘libcod’ указан дважды»). Но я не могу использовать «insertable = false» при определении JoinColumn («Смешивание вставляемых и не вставляемых столбцов в свойстве не допускается»).
Есть ли какой-либо способ определить эти объекты отношения, чтобы столбцы автоматически управлялись Hibernate?
Ответ №1:
Hibernate и JPA автоматически делают постоянными все изменения, внесенные в постоянные объекты, пока они присоединены к сеансу. В этом весь смысл ORM: вы загружаете постоянный объект, изменяете его, и новое состояние автоматически сохраняется при фиксации транзакции, без необходимости вызывать persist, merge, save или любой другой метод.
Обратите внимание, что вызов persist
постоянных объектов (за исключением его каскадных побочных эффектов) не имеет смысла. persist
заключается в том, чтобы сделать временный объект (т. Е. Новый, Которого еще нет в базе данных, без сгенерированного идентификатора) постоянным.
Комментарии:
1. Неважно. Я настраивал свои тесты в спешке и допустил несколько ошибок. Предполагалось, что тесты будут выполняться с отдельными объектами. Сейчас я столкнулся с новой проблемой, поэтому, пожалуйста, проверьте отредактированный вопрос. Спасибо.
2. Здесь у вас действительно странная схема: было бы невозможно изменить язык книги, не изменив ее первичный ключ. Я бы использовал суррогатные ключи с одним столбцом. И если вы не можете, тогда у меня было бы два отдельных столбца libcod: один для первичного ключа книги и один для внешнего ключа языка.
3. Проблема в том, что я не могу изменить структуру базы данных. Мне ПРИХОДИТСЯ работать с этой устаревшей базой данных, поэтому я пытаюсь найти наиболее элегантный способ описания и управления ею через JPA. Конечно, я бы предпочел иметь простые идентификаторы для PK и FK, но …
Ответ №2:
У вас может быть только один мутатор для libcod. Вероятно, что вам следует сделать, это оставить средство получения libcod в классе BookPK, а в классе Language использовать ссылку joincolumn с ссылкой на libcod. Он отлично работает для отдельных встроенных классов PK, но для нескольких классов PK вам, возможно, придется поиграть.
Итак, в вашем языковом классе у вас будет это.
@javax.persistence.Entity public class Language {
private LanguagePK id;
private Integer libcod;
@javax.persistence.EmbeddedId @AttributeOverrides({
@AttributeOverride(name = "lngcod", column = @Column(name = "LNGCOD", nullable = false)),
@AttributeOverride(name = "libcod", column = @Column(name = "LIBCOD", nullable = false)) })
public LanguagePK getId() {
return this.id;
}
public void setId(LanguagePK id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "LIBCOD", insertable = false , updatable = false)
public Integer getLibcod() {
return this.libcod;
}