阅读 35

【JPA专题】06.映射关系_多对一单向

映射关系

A.多对一单向映射关系

基础关系代码:一方班级类

package com.os.model;

import javax.persistence.*;

@Entity
@Table(name = "jpa_class")
public class ClassInfo {
    private Integer classId;
    private String className;

    public ClassInfo(){}

    public ClassInfo( String className) {
        this.className = className;
    }
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getClassId() {
        return classId;
    }

    public void setClassId(Integer classId) {
        this.classId = classId;
    }
    @Column(name = "class_name")
    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

}
复制代码

基础关系代码:多方方学生类

@Entity
@Table(name = "jpa_student")
public class Student {

    private Integer studentId;
    private String studentName;
    private String sex;

    private ClassInfo classInfo;

    public Student() {}

    public Student(String studentName, String sex) {
        this.studentName = studentName;
        this.sex = sex;
    }
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getStudentId() {
        return studentId;
    }

    public void setStudentId(Integer studentId) {
        this.studentId = studentId;
    }
    @Column(name = "student_name")
    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
    /*
    * 映射多对一的单向关系,@ManyToOne
    * 使用@JoinColumn指定外键字段
    * */
    @ManyToOne
    @JoinColumn(name = "class_id")
    public ClassInfo getClassInfo() {
        return classInfo;
    }

    public void setClassInfo(ClassInfo classInfo) {
        this.classInfo = classInfo;
    }
}
复制代码

关联关系建立请看注释说明,特别说明:没有生成物理关联,原因不明

public class JPATest {

    private EntityManagerFactory factory ;
    private EntityManager entityManager ;
    private EntityTransaction tx;
    @Before
    public void init(){
        factory = Persistence.createEntityManagerFactory("jpa03");
        entityManager = factory.createEntityManager();
        tx = entityManager.getTransaction();
        tx.begin();
    }
    @After
    public void close(){
        tx.commit();
        entityManager.close();
        factory.close();
    }
}
复制代码

1.先保存一方在保存多方

@Test
public void test01(){
    ClassInfo classInfo = new ClassInfo("起航班级");

    Student s1 = new Student("小白","男");
    Student s2 = new Student("大黄","男");
    //多方维护关系
    s1.setClassInfo(classInfo);
    s2.setClassInfo(classInfo);
    //先保存一方,在保存多方
    entityManager.persist(classInfo);
    entityManager.persist(s1);
    entityManager.persist(s2);

}
复制代码

控制台生成了三条SQL语句

2.先保存多方在保存一方

@Test
public void test02(){
    ClassInfo classInfo = new ClassInfo("扬帆班级");

    Student s1 = new Student("小智","女");
    Student s2 = new Student("无脑","女");
    //多方维护关系
    s1.setClassInfo(classInfo);
    s2.setClassInfo(classInfo);
    //先保存多方,在保存一方
    entityManager.persist(s1);
    entityManager.persist(s2);
    entityManager.persist(classInfo);
}
复制代码

控制台生成了五条条SQL语句:3条添加语句,2条更新语句

推荐:先保存一方,再保存多方,不会多出额外的update语句

3.获取某个学生和对应的班级信息

@Test
public void test03(){
    Student s1 = entityManager.find(Student.class,3);
    System.out.println(s1.getStudentName());
    System.out.println(s1.getClassInfo().getClassName());
}
复制代码
Hibernate: 
    select
        student0_.id as id1_1_0_,
        student0_.class_id as class_id4_1_0_,
        student0_.sex as sex2_1_0_,
        student0_.student_name as student_3_1_0_,
        classinfo1_.id as id1_0_1_,
        classinfo1_.class_name as class_na2_0_1_ 
    from
        jpa_student student0_ 
    left outer join
        jpa_class classinfo1_ 
            on student0_.class_id=classinfo1_.id 
    where
        student0_.id=?
复制代码

默认情况下,使用左外连接的方式来获取多方的对象和其关联的一方的对象

设置懒加载方式

/*
* 映射多对一的单向关系,@ManyToOne
* 使用@JoinColumn指定外键字段
* */
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "class_id")
public ClassInfo getClassInfo() {
    return classInfo;
}
复制代码

可以使用@ManyToOne中的属性fetch属性来修改默认的加载策略

@Test
public void test03(){
    Student s1 = entityManager.find(Student.class,3);
    System.out.println(s1.getStudentName());
    System.out.println(s1.getClassInfo().getClassName());//关联对象延迟加载,使用才会去查询
}
复制代码

再次运行效果,产生的SQL语句为

Hibernate: 
    select
        student0_.id as id1_1_0_,
        student0_.class_id as class_id4_1_0_,
        student0_.sex as sex2_1_0_,
        student0_.student_name as student_3_1_0_ 
    from
        jpa_student student0_ 
    where
        student0_.id=?
Hibernate: 
    select
        classinfo0_.id as id1_0_0_,
        classinfo0_.class_name as class_na2_0_0_ 
    from
        jpa_class classinfo0_ 
    where
        classinfo0_.id=?
复制代码

4.删除某个学生

@Test
public void test04(){
    Student s1 = entityManager.find(Student.class,3);
    entityManager.remove(s1);
}
复制代码
Hibernate: 
    select
        student0_.id as id1_1_0_,
        student0_.class_id as class_id4_1_0_,
        student0_.sex as sex2_1_0_,
        student0_.student_name as student_3_1_0_ 
    from
        jpa_student student0_ 
    where
        student0_.id=?
Hibernate: 
    delete 
    from
        jpa_student 
    where
        id=?
复制代码

删除班级主键为1的信息,无法进行删除,因为存在外键的约束条件,

在前面我也说过了,虽然指定了外键,没有生成物理关联,所以还是逻辑关联,班级信息能进行删除,尴尬了!

@Test
public void test05(){
    ClassInfo c1 = entityManager.find(ClassInfo.class,1);
    entityManager.remove(c1);
}
复制代码

5.修改学生对应的班级名称,更新操作

@Test
public void test06(){
    Student s1 = entityManager.find(Student.class,4);
    s1.getClassInfo().setClassName("无敌班级");
}
复制代码
Hibernate: 
    select
        student0_.id as id1_1_0_,
        student0_.class_id as class_id4_1_0_,
        student0_.sex as sex2_1_0_,
        student0_.student_name as student_3_1_0_ 
    from
        jpa_student student0_ 
    where
        student0_.id=?
Hibernate: 
    select
        classinfo0_.id as id1_0_0_,
        classinfo0_.class_name as class_na2_0_0_ 
    from
        jpa_class classinfo0_ 
    where
        classinfo0_.id=?
Hibernate: 
    update
        jpa_class 
    set
        class_name=? 
    where
        id=?
复制代码