Hibernate - ManyToOne - Сохранить - org.hibernate.TransientObjectException: - PullRequest
1 голос
/ 14 декабря 2009

Пока я пытаюсь сохранить сущность верхнего уровня (используя JPA), нужно ли мне заново получать сопоставленную сущность ManyToOne из базы данных и устанавливать ее, или я не могу просто установить Id (сопоставленной сущности manyToOne и сохранить сущность верхнего уровня? Когда не получается новая сущность, она выдает: org.hibernate.TransientObjectException:

Структуры таблиц, которые мы используем:

DEPARTMENT(DEPARTMENT_ID BIGINT, NAME VARCHAR(128))

EMPLOYEE(EMPLOYEE_ID BIGINT, NAME VARCHAR(128), DEPARTMENT_ID BIGINT)

Entities:
class Department
{
   @Id
   Long departmentId;
   String name;
   @Version
   Long versionNumber;
}

class Employee
{
   @Id
   Long employeeId;
   String name;
   @ManyToOne
   Department department;
   @Version
   Long versionNumber
}

(оба класса имеют методы установки и получения для всех полей и конструктор по умолчанию, конструктор, который принимает первичный ключ в качестве аргумента) Теперь, если я хочу сохранить Employee с значением DepartmentId (скажем, 100), нужно ли сначала получить запись отдела, а затем установить ее для сотрудника?

Не могу ли я создать экземпляр Отдела напрямую (путем установки первичного ключа (DepartmentId)) и задать экземпляр Отдела в Employee и сохранить Employee? Когда я делаю это, он выдает org.hibernate.TransientObjectException.

Есть ли какие-либо предложения по наилучшей практике для этого?

Заранее спасибо

Ответы [ 3 ]

7 голосов
/ 14 декабря 2009

Если вы хотите связать свой экземпляр Employee с новым `экземпляром отдела, вы можете установить соответствующее каскадное поведение и позволить Hibernate позаботиться обо всем этом:

class Employee {
  ...
  @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
  Department department;
}

Обратите внимание, что вы НЕ хотите использовать CascadeType.ALL, поскольку удаление сотрудника не должно удалять отдел.

Если, OTOH, вы хотите связать свой экземпляр Employee с существующим `экземпляром Department, ваш лучший подход - действительно загрузить его. Для этой цели вы можете использовать метод session.load () , который не ударит по базе данных .

Альтернативным решением является использование session.merge () на Employee, которое (с каскадированием, как указано выше) будет распространяться до Department. Это может иметь побочные эффекты.

1 голос
/ 15 декабря 2009

Спасибо ChssPly76 и Wysawyg.

Одним из решений может быть: Мы обновим POJO сотрудника, как показано ниже

ManyToOne(fetch=FetchType.EAGER)
@**JoinColumn**(name = "DEPARTMENT_ID", referencedColumnName = "DEPARTMENT_ID", **insertable=false, updatable=false**)
private Department department;

@Column(name = "department_id")
private Long departmentId;

(и для отдела, и для департамента будут методы установки и получения)

и сейчас здесь (пожалуйста, обратите внимание, что ИД отдела и отдела сопоставлен с одним и тем же столбцом (DEPARTMENT_ID), который мы используем Отдел только для получения сведений об отделе и ИД отдела для вставки или обновления Сотрудник

Но я волнуюсь, если это лучший подход.

1 голос
/ 14 декабря 2009

Если вы хотите сохранить родительский элемент без сохранения каждого из дочерних элементов, вам необходимо отобразить его примерно так (не помню точный синтаксис)

@ManyToOne(CascadeType = Cascade.All)
Department department;

РЕДАКТИРОВАТЬ: я сделал ошибку, рассматривая его как родитель к ребенку вместо ребенка к родителю. Следуйте примеру ChssPly76.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...