@Entity @Table(name="T_MANAGER") public class Manager { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="MANA_ID") private int id; @Column(name="MANA_NAME") private String name; } @Entity @Table(name="T_EMPLOYEE") public class Employee { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="EMPL_ID") private int id; @Column(name="EMPL_NAME") private String name; @ManyToOne(cascade=CascadeType.PERSIST) private Manager manager; }
Domain model
T_EMPLOYEE.MANAGER_MANA_ID is the foreign key referenced to T_MANAGER.MANA_ID
MANAGER_MANA_ID is the default foreign key column name. It is derived from class name + ‘_’ + primary key name (‘MANAGER’ + ‘_’+’MANA_ID’)
Test:
@PersistenceContext(unitName="unit") private EntityManager em; private void save(){ Manager manager1 = new Manager("John"); Employee employee1 = new Employee("Bob"); Employee employee2 = new Employee("Tim"); Employee employee3 = new Employee("Mary"); employee1.setManager(manager1); employee2.setManager(manager1); employee3.setManager(manager1); Manager manager2 = new Manager("Robert"); Employee employee4 = new Employee("Tom"); Employee employee5 = new Employee("Alex"); employee4.setManager(manager2); employee5.setManager(manager2); em.persist(employee1); em.persist(employee2); em.persist(employee3); em.persist(employee4); em.persist(employee5); }Result:
T_MANAGER
T_EMPLOYEE
Specify foreign key column name
@OneToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, optional=false, fetch=FetchType.EAGER) @JoinColumn(name="F_ADDR_ID", referencedColumnName="ADDR_ID") private Address address;
Domain model
The name attribute of @JoinColumn (‘F_MANA_ID’) specifies the foreign key column name.
many-to-one bidirectional mapping
@Entity @Table(name="T_MANAGER") public class Manager { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="MANA_ID") private int id; @Column(name="MANA_NAME") private String name; @OneToMany(cascade={CascadeType.ALL}, mappedBy="manager") private Set<Employee> employees; } @Entity @Table(name="T_EMPLOYEE") public class Employee { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="EMPL_ID") private int id; @Column(name="EMPL_NAME") private String name; @ManyToOne(cascade=CascadeType.PERSIST) @JoinColumn(name="F_MANA_ID") private Manager manager; }
Domain model
Same as unidirectional mapping
Test:
@PersistenceContext(unitName="unit") private EntityManager em; private void save(){ Manager manager1 = new Manager("John"); Employee employee1 = new Employee("Bob"); Employee employee2 = new Employee("Tim"); Employee employee3 = new Employee("Mary"); Set<Employee> employees1 = new HashSet<Employee>(); employee1.setManager(manager1); employee2.setManager(manager1); employee3.setManager(manager1); employees1.add(employee1); employees1.add(employee2); employees1.add(employee3); manager1.setEmployees(employees1); Manager manager2 = new Manager("Robert"); Employee employee4 = new Employee("Tom"); Employee employee5 = new Employee("Alex"); Set<Employee> employees2 = new HashSet<Employee>(); employees2.add(employee4); employees2.add(employee5); employee4.setManager(manager2); employee5.setManager(manager2); manager2.setEmployees(employees2); em.persist(manager1); em.persist(manager2); }
Result:
Same as unidirectional mapping
T_MANAGER
Retrieving the employees of a manager returns null.
Manager manager = em.find(Manager.class, 1);
System.out.println(manager.getEmployees());
This is because in a one-to-many relationship, the default fetch type at ONE side is LAZY.
@OneToMany(cascade={CascadeType.ALL}, mappedBy="manager", fetch=FetchType.EAGER) private Set<Employee> employees;
Change the fetch type to EAGER, and we are able to retrieve the employees of a manager.
Add a new employee to a manager
Manager manager = em.find(Manager.class, 1); Employee emp = new Employee("Adam"); emp.setManager(manager); manager.getEmployees().add(emp); em.merge(manager);
Result:
Update an existing employee of a manager
Manager manager = em.find(Manager.class, 1); Employee employee = manager.getEmployees().iterator().next(); employee.setName("Josh"); em.merge(manager);
Result:
Delete an existing employee of a manager
Manager manager = em.find(Manager.class, 1); Set<Employee> employees= manager.getEmployees(); for (Employee emp: employees){ if ("Bob".equalsIgnoreCase(emp.getName())){ employees.remove(emp); break; } } em.merge(manager);
Result:
Bob is not deleted! We can see that simply removing the object from the set won’t actually remove the row from the database. So in this case, we need to invoke em.remove() to delete the row.
Manager manager = em.find(Manager.class, 1); Set<Employee> employees= manager.getEmployees(); for (Employee emp: employees){ if ("Bob".equalsIgnoreCase(emp.getName())){ employees.remove(emp); em.remove(emp); break; } } em.merge(manager);
Result:
No comments:
Post a Comment