JPA進階-對象關係映射

我的網站:歡迎大家訪問

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"的話每次查詢都會把全部數據刪除完,真是血的教訓!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章