我的網站:歡迎大家訪問
JPA進階-映射
一對多關係
單向
單向一對多用得比較少(性能差),但是還是需要了解,單向一對多其實就是在主表中添加ManyToOne的註解即可
雙向
同時在兩個類中添加註解,在使用雙向連接的時候,主從表外鍵名稱必須一致
這裏設計主表爲Department
package com.ifueen.domian;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "department")
public class Department {
@Id
@GeneratedValue
private Long id;
private String name;
public Department() {
}
@Override
public String toString() {
return "Department{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getList() {
return list;
}
public void setList(List<Employee> list) {
this.list = list;
}
@OneToMany(cascade = CascadeType.ALL,mappedBy = "department",fetch = FetchType.LAZY,orphanRemoval = true)
//@JoinColumn(name = "department_id")
List<Employee> list= new ArrayList<Employee>();
}
從表Employee的設計
package com.ifueen.domian;
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee {
public Employee() {
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + '\'';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Department department;
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
兩個表的實體類創建好之後,測試以下,如果沒有報錯那麼就表示成功了
/**
* 測試添加功能是否成功
*
*/
@Test
public void test1(){
EntityManager jpa = JPAUtil.getJpa();
Employee employee = new Employee();
employee.setName("庫布里奇");
Employee employee1 = new Employee();
employee1.setName("希區柯克");
Department department = new Department();
department.setName("電影");
/* department.getList().add(employee);
department.getList().add(employee1);*/
employee.setDepartment(department);
employee1.setDepartment(department);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(department);
jpa.persist(employee);
jpa.persist(employee1);
transaction.commit();
jpa.close();
}
級聯操作
爲什麼需要將兩張表關聯起來呢?因爲將它們進行關聯以後,我們便可以進行級聯操作,雖然平時用的可能不是太多
級聯添加
進行主表的添加,只需要設置好從表的數據,那麼從表也會將數據添加進去
/**
* 級聯添加
* 雙方都需要建立連接和維護
* 在添加的時候只需要添加主表,從表的數據也會隨之添加
*/
@Test
public void test2(){
EntityManager jpa = JPAUtil.getJpa();
Employee employee = new Employee();
employee.setName("庫布里奇");
Employee employee1 = new Employee();
employee1.setName("希區柯克");
Department department = new Department();
department.setName("電影");
department.getList().add(employee);
department.getList().add(employee1);
employee.setDepartment(department);
employee1.setDepartment(department);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(department);
transaction.commit();
jpa.close();
}
級聯刪除(慎用!容易遭到整個項目組的毒打)
/**
* 級聯刪除
*/
@Test
public void test3(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Department department = jpa.find(Department.class, 1L);
System.out.println(department);
jpa.remove(department);
transaction.commit();
jpa.close();
}
/**
* 級聯刪除,通過主表刪除從表相關的數據
*/
@Test
public void test4(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
String hql = "update Employee e set e.department = null";
Query query = jpa.createQuery(hql);
query.executeUpdate();
Department department = jpa.find(Department.class, 2L);
jpa.remove(department);
transaction.commit();
jpa.close();
}
/**
* 直接刪除多方,不經過主表,主表不會受到影響
*/
@Test
public void test5(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Employee employee = jpa.find(Employee.class, 5L);
jpa.remove(employee);
transaction.commit();
jpa.close();
}
/**
* 級聯刪除,使用髒數據更新,通過主表刪除從表相對應的數據
*/
@Test
public void test6(){
EntityManager jpa = JPAUtil.getJpa();
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
Department department = jpa.find(Department.class, 2L);
//髒數據更新
department.getList().clear();
transaction.commit();
jpa.close();
}
多對多關係
單向多對多
單向的多對多其實用的都挺少的,而且使用單向,建表sql語句的冗餘度也挺高的,所以這裏不進行總結,如果需要了解,可以自行網上搜索一下
雙向多對多
這裏實現一個案例,通過案例來協助掌握雙向多對多
兩個表,user和role,分別對應導演和作品的,使他們之間進行關聯起來
User表設計
package com.ifueen.domian;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "t_user_role",joinColumns = {@JoinColumn(name = "user_id")},inverseJoinColumns = {@JoinColumn(name = "role_id")})
private List<Role> roles = new ArrayList<Role>();
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Role表設計
package com.ifueen.domian;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue
private Long id;
private String name;
public Role() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "t_user_role",joinColumns = {@JoinColumn(name = "role_id")},inverseJoinColumns = {@JoinColumn(name = "user_id")})
private List<User> users = new ArrayList<User>();
@Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
兩張表的實體類設計好,現在測試
/**
* 多對多連接,生成表
*/
@Test
public void test(){
EntityManager jpa = JPAUtil.getJpa();
}
表結構就搭建好了
下面就可以寫功能進行測試
/**
* 多對多連接,添加
*/
@Test
public void test1(){
EntityManager jpa = JPAUtil.getJpa();
User user = new User();
user.setName("黑澤明");
User user1 = new User();
user1.setName("庫布里克");
User user2 = new User();
user2.setName("諾蘭");
Role role = new Role();
role.setName("七武士");
Role role1 = new Role();
role1.setName("2001太空漫步");
Role role2 = new Role();
role2.setName("星際穿越");
Role role3 = new Role();
role3.setName("黑暗騎士");
//維護關係
user.getRoles().add(role);
user1.getRoles().add(role1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(user);
jpa.persist(user1);
jpa.persist(user2);
jpa.persist(role);
jpa.persist(role1);
jpa.persist(role2);
jpa.persist(role3);
transaction.commit();
jpa.close();
}
/**
* 查詢
*/
@Test
public void test2(){
EntityManager jpa = JPAUtil.getJpa();
User user = jpa.find(User.class, 3L);
System.out.println(user);
List<Role> roles = user.getRoles();
roles.forEach(System.out::println);
jpa.close();
}
/**
* 多對多連接,只需要添加一張表
*/
@Test
public void test3(){
EntityManager jpa = JPAUtil.getJpa();
User user = new User();
user.setName("黑澤明");
User user1 = new User();
user1.setName("庫布里克");
User user2 = new User();
user2.setName("諾蘭");
Role role = new Role();
role.setName("七武士");
Role role1 = new Role();
role1.setName("2001太空漫步");
Role role2 = new Role();
role2.setName("星際穿越");
Role role3 = new Role();
role3.setName("黑暗騎士");
//維護關係
user.getRoles().add(role);
user1.getRoles().add(role1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);
EntityTransaction transaction = jpa.getTransaction();
transaction.begin();
jpa.persist(user);
jpa.persist(user1);
jpa.persist(user2);
transaction.commit();
jpa.close();
}
/**
* 刪除,沒有配置級聯刪除
*
*/
@Test
public void test4(){
EntityManager jpa = JPAUtil.getJpa();
jpa.getTransaction().begin();
User user = jpa.find(User.class, 3L);
jpa.remove(user);
jpa.getTransaction().commit();
jpa.close();
}
注意,在使用除了添加功能的時候,需要在生成組策略中配置爲,如果value="create"的話每次查詢都會把全部數據刪除完,真是血的教訓!!