欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JPA3--双向与级联操作

程序员文章站 2022-05-02 08:18:04
...

JPA3–双向与级联操作

一 、单向一对多

1.1配置

在一方配置onetomany

@Entity
@Table(name="t_productDir")
public class ProductDir {
    @Id
    @GeneratedValue
    private Long id;
    private String name;

    //配置多方 List/Set
    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name="dir_id")
    @OrderBy("price desc")
    private List<Product> products = new ArrayList<>();

多方配置:

@Entity
@Table(name="t_product")
public class Product {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
1.2保存操作:

不管是先保存一方还是多方,都有额外发送sql ,效率上面比较低,建议使用单向多对一,如果要学习双向 这个也要学习

1.3在使用集合的时候,使用接口 比如List/Set(掌握)

List主要有顺序上面 比如组合就可以使用
Set主要多对多 多对一上面 没有顺序 但是orderby 也可以排序

二、双向多对一或者一对多

2.1配置:
@Entity
public class ProductDir {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  @OneToMany(mappedBy=”dir”)
  // @JoinColumn(name="dir_id")
  private Set<Product> products = new HashSet<Product>();
  
@Entity
public class Product {
  @Id
  @GeneratedValue
  private Long id;
  private String name;
  @ManyToOne(fetch = FetchType.LAZY) // 实现延迟加载
  @JoinColumn(name = "dir_id")
  private ProductDir dir;
}
2.2保存代码案例:
public void testManytoOne2() throws Exception{
    //保存数据
    Product  product1= new Product();
    product1.setName("华硕飞行堡垒");

    Product product2 = new Product();
    product2.setName("联想拯救者");

    ProductDir dir = new ProductDir();
    dir.setName("笔记本电脑");

    //设置关系
    dir.getProducts().add(product1);
    dir.getProducts().add(product2);

    product1.setDir(dir);
    product2.setDir(dir);

    //保存
    EntityManager entityManager = JpaUtils.getEntityManager();
    entityManager.getTransaction().begin();

    //双向的
    entityManager.persist(dir);
    entityManager.persist(product1);
    entityManager.persist(product2);
    
    entityManager.getTransaction().commit();
    entityManager.close();
2.3级联操作
配置:
级联保存((mappedBy = "dir" 表示将外键的维护交给多方管理,dir表示多方中字段属性名,,cascade = CascadeType.PERSISIT 表示可以使用级联保存,除了PERSISIT,常用的还有ALL ,remove)
@OneToMany(mappedBy = "dir",cascade = CascadeType.PERSISIT)
@Test
public void testCascade() throws Exception{
    //保存数据
    Product  product1= new Product();
    product1.setName("被子");

    Product product2 = new Product();
    product2.setName("枕头");

    ProductDir dir = new ProductDir();
    dir.setName("床上用品");

    //设置关系
    dir.getProducts().add(product1);
    dir.getProducts().add(product2);
    product1.setDir(dir);
    product2.setDir(dir);
    //保存
    EntityManager entityManager = JpaUtils.getEntityManager();
    entityManager.getTransaction().begin();
    //双向的(保存乙方自动保存另外一方想关的)
    entityManager.persist(dir);

    entityManager.getTransaction().commit();
    entityManager.close();

}

级联删除

@OneToMany(mappedBy = "dir",cascade = CascadeType.REOMOVE)
//级联删除:删除一方,然后级联删除多方
@Test
public void testDelete1() throws Exception{

    //删除分类7的时候,把多方也删除
    EntityManager entityManager = JpaUtils.getEntityManager();
    entityManager.getTransaction().begin();
    ProductDir productDir = entityManager.find(ProductDir.class, 1L);

    entityManager.remove(productDir);

    entityManager.getTransaction().commit();
    entityManager.close();

三、单向多对多

3.1配置
用户配置:
@Table(name="t_user")
public class User {

    @Id
    @GeneratedValue
    private Long id;

    private String name;
    
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name="t_user_role",joinColumns ={@JoinColumn(name="user_id")},inverseJoinColumns = {@JoinColumn(name="role_id")})
    private Set<Role> roles = new HashSet<>();

角色:
@Entity
@Table(name="t_role")
public class Role {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
3.2保存操作
public void testCreat() throws Exception{
        JpaUtil.getEntityManager();
        // 保存2个用户,保存3个角色(5条)
        User user1 = new User();
        user1.setName("猪儿虫");
        User user2 = new User();
        user2.setName("猪八戒");
        Role role1 = new Role();
        role1.setName("司机");
        Role role2 = new Role();
        role2.setName("演员");
        Role role3 = new Role();
        role3.setName("验黄师");
        // 保存中间表:建立用户到角色关系user1(role1,role2),user2(role1,role2,role3)(5条)
        user1.getRoles().add(role1);
        user1.getRoles().add(role2);

        user2.getRoles().add(role1);
        user2.getRoles().add(role2);
        user2.getRoles().add(role3);

        EntityManager entityManager = JpaUtil.getEntityManager();
        entityManager.getTransaction().begin();

        //保存用户
        entityManager.persist(user1);
        entityManager.persist(user2);
        // 保存角色
        entityManager.persist(role1);
        entityManager.persist(role2);
        entityManager.persist(role3);

        entityManager.getTransaction().commit();
        entityManager.close();
    }

四、双向的多对多

4.1配置:
//学生配置
@Entity
@Table(name = "t_student")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    //级联保存的配置
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name="t_student_teacher",joinColumns = {@JoinColumn(name="stu_id")},inverseJoinColumns ={@JoinColumn(name = "t_id")})
    private Set<Teacher> tset = new HashSet<>();

    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 Set<Teacher> getTset() {
        return tset;
    }

    public void setTset(Set<Teacher> tset) {
        this.tset = tset;
    }

//老师配置
@Entity
@Table(name="t_teacher")
public class Teacher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @JoinColumn(name="t_name")
    private  String name;
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name="t_student_teacher",joinColumns = {@JoinColumn(name="t_id")},inverseJoinColumns ={@JoinColumn(name = "stu_id")})
    private Set<Student> cont = new HashSet<>();

    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 Set<Student> getCont() {
        return cont;
    }

    public void setCont(Set<Student> cont) {
        this.cont = cont;
    }
4.2级联操作和其他操作:
 //级联保存操作  需要的配置(@manytomany(cascade = CascadeType.PERSIST))PERSIST 表示只能级联保存,可以有all,remove配置
    @Test
    public void testAdd() throws Exception{
        EntityManager entityManager = JpaUtil.getEntityManager();
        Student student1 = new Student();
        Student student2 = new Student();
        Student student3 = new Student();
        student1.setName("王大锤");
        student2.setName("刘全有");
        student3.setName("张全蛋");
        Teacher teacher1 = new Teacher();
        Teacher teacher2 = new Teacher();
        teacher1.setName("孙悟空");
        teacher2.setName("邱少华");
        student1.getTset().add(teacher1);
        student1.getTset().add(teacher2);
        student2.getTset().add(teacher2);
        student2.getTset().add(teacher1);
        student3.getTset().add(teacher1);
        entityManager.getTransaction().begin();
        entityManager.persist(student1);
        entityManager.persist(student2);
        entityManager.persist(student3);
        entityManager.getTransaction().commit();
    }
 public void testDelete() throws Exception{
        //普通的删除(会删除查找的数据,并且删除Id相关表的关系链接)
        EntityManager entityManager = JpaUtil.getEntityManager();
        Student student = entityManager.find(Student.class, 1L);
        entityManager.getTransaction().begin();
        entityManager.remove(student);
        entityManager.getTransaction().commit();
    }
    //删除student2与teacher2的关联
    @Test
    public void testDelete2() throws Exception{
        EntityManager entityManager = JpaUtil.getEntityManager();
        Student student2 = entityManager.find(Student.class, 2L);
        Teacher teacher = entityManager.find(Teacher.class, 2L);
        entityManager.getTransaction().begin();
        student2.getTset().remove(teacher);
        entityManager.getTransaction().commit();
    }
    //删除student3的所有teacher相关的关系
    @Test
    public void testDelete3() throws Exception{
        EntityManager entityManager = JpaUtil.getEntityManager();
        Student student3 = entityManager.find(Student.class, 3L);
        entityManager.getTransaction().begin();
        student3.getTset().clear();
        entityManager.getTransaction().commit();
    }
    //级联删除
    @Test
    public void testJLdelete() throws Exception{
        //第一步配置级联删除
        EntityManager entityManager = JpaUtil.getEntityManager();
        Student student = entityManager.find(Student.class, 1L);
        entityManager.getTransaction().begin();
        entityManager.remove(student);
        entityManager.getTransaction().commit();

    }

五、Jpa的优化:
常用:
(1)尽量使用单向多对一去代替单向一对多
如果实在要使用双向的配置,尽量的一方放弃管理
(2)常用多对多的配置,中间表会自动产生,jointable
单向和双向
(3)一对一 看特殊的 多对一 -->基本不用
注意:实在要使用一对一 尽量使用唯一的外键
(4)表字段尽量少,(有缓存),表不要怕多,jpa自动创建好这个关系