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"的话每次查询都会把全部数据删除完,真是血的教训!!

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