Мне не хватает чего-то очень фундаментального. Ниже приведены два объекта Department
(обратная сторона) и Employee
(владеющая сторона), образующая отношение «один ко многим» от Department
до Employee
.Двунаправленные отношения в JPA
Department.java
@Entity
@Table(catalog = "testdb", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"department_id"})})
public class Department implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "department_id", nullable = false)
private Long departmentId;
@Column(name = "department_name", length = 255)
private String departmentName;
@Column(length = 255)
private String location;
@OneToMany(mappedBy = "department", fetch = FetchType.LAZY)
private List<Employee> employeeList = new ArrayList<Employee>(0);
private static final long serialVersionUID = 1L;
// Constructors + getters + setters + hashcode() + equals() + toString().
// No defensive link (relationship) management methods have yet been added to.
// CascadeType is also kept at a distance for now.
}
Employee.java
@Entity
@Table(catalog = "testdb", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"employee_id"})})
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "employee_id", nullable = false)
private Long employeeId;
@Column(name = "employee_name", length = 255)
private String employeeName;
@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
private static final long serialVersionUID = 1L;
// Constructors + getters + setters + hashcode() + equals() + toString().
// No defensive link (relationship) management methods have yet been added to.
// CascadeType is also kept at a distance for now.
}
Ниже некоторые методы в безгосударственном EJB (с использованием СМТА) делают не проходит, объединять и удалять операции соответственно.
public List<Employee> persist() {
Employee employee = new Employee();
employee.setEmployeeName("a");
employee.setDepartment(entityManager.getReference(Department.class, 1L));
entityManager.persist(employee);
return employee.getDepartment().getEmployeeList();
}
public List<Employee> merge(Employee employee) {
employee.setEmployeeName("b");
employee.setDepartment(entityManager.getReference(Department.class, 1L));
return entityManager.merge(employee).getDepartment().getEmployeeList();
}
public List<Employee> remove(Employee employee) {
entityManager.remove(entityManager.contains(employee) ? employee : entityManager.merge(employee));
return entityManager.getReference(Employee.class, employee.getEmployeeId()).getDepartment().getEmployeeList();
}
public Employee getEmployeeById(Long id) {
return entityManager.find(Employee.class, id);
}
Эти методы вызываются связанным клиентом приложения поочередно (один за другим) в не транзакционной среде.
List<Employee> persistedList = employeeSessionBean.persist();
for (Employee employee : persistedList) {
System.out.println(employee.getEmployeeId() + " : " + employee.getEmployeeName());
}
List<Employee> mergedList = employeeSessionBean.merge(employeeSessionBean.getEmployeeById(23L));
for (Employee employee : mergedList) {
System.out.println(employee.getEmployeeId() + " : " + employee.getEmployeeName());
}
List<Employee> listAfterRemoving = employeeSessionBean.remove(employeeSessionBean.getEmployeeById(23L));
for (Employee employee : listAfterRemoving) {
System.out.println(employee.getEmployeeId() + " : " + employee.getEmployeeName());
}
В списке (List<Employee>
) на обратной стороне отношений автоматически отражает правильное состояние во время каждой операции, как указано выше.
- Когда
Employee
объекта сохраняются, она указана в списке на обратной сторона (я явно не добавляя новый сохранялосьEmployee
сущности кList<Employee>
на обратной стороне). - При объединении объекта
Employee
изменения, внесенные в объект, автоматически отражаются соответствующим субъектом вList<Employee>
на обратной стороне (я не изменяю явным образом соответствующий объект, принадлежащий списку сотрудников (List<Employee>
) на обратном боковая сторона). - Аналогично, когда объект
Employee
удален, он также удаляется из списка на обратной стороне отношения (я не , явно удаляющий этот объект из списка на обратной стороне).
Я в настоящее время на EcliseLink 2.6.0. Почему я вижу такое поведение, которое не соответствует следующему тексту?
Как и во всех двунаправленных отношениях это ваша объектная модель и ответственности приложения для поддержания отношений в обоих направлении. В JPA нет магии, если вы добавите или удалите одну сторону из коллекции, вам необходимо также добавить или удалить с другой стороны, см. object corruption. Технически база данных будет обновлена правильно, если вы только добавите/удалите с собственной стороны отношения , но тогда ваша объектная модель будет не синхронизирована, что может вызвать проблемы .
http://en.wikibooks.org/wiki/Java_Persistence/ManyToMany#Bi-directional_Many_to_Many
Ничего себе, я никогда не видел, чтобы кто-то жаловался на программное обеспечение, делающее ** больше **, чем они ожидали! – DuncanKinnear