Hibernate -- 映射实体关联关系(多对多关联关系)

以学生和课程之间的关系为例

学生表为t_student,课程表为t_course
这里以Student实体类控制关联关系


1.编写实体类 Student

/**
 * Hibernate的注解类包名为javax.persistence
 */
@Entity                   // 将一个Java类声明为一个POJO类(实体类)
@Table(name = "t_student")//声明了该实体映射所指定的表,该类属性name指定表名
public class Student implements java.io.Serializable {

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

    private Set<Course> cous = new HashSet<Course>();

    public Student() {
    }

    public Student(String studentName, String sex, String age) {
        this.studentName = studentName;
        this.sex = sex;
        this.age = age;
    }

    @Id  //声明了该实体的标识属性,该属性对应表中的主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)//声明了主键的生成策略为自增长,默认值为GenerationType.AUTO
    @Column(name = "student_id")  //声明了属性到列的映射
    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;
    }

    @Column(name = "s_sex")  //声明了属性到列的映射
    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Column(name = "s_age")  //声明了属性到列的映射
    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    @ManyToMany(fetch = FetchType.LAZY, targetEntity = Course.class, cascade = CascadeType.ALL)
    @JoinTable(name = "stu_cou", joinColumns = { @JoinColumn(name = "student_id") }, 
    inverseJoinColumns = {@JoinColumn(name = "course_id") })
    public Set<Course> getCous() {
        return cous;
    }

    public void setCous(Set<Course> ones) {
        cous = ones;
    }

}

2.编写实体类 Course

package com.zr.obj;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity                  // 将一个Java类声明为一个POJO类(实体类)
@Table(name = "t_course")//声明了该实体映射所指定的表,该类属性name指定表名
public class Course implements java.io.Serializable {

    private Integer courseId;
    private String courseName;
    private String teacher;
    private String classroom;

    private Set<Student> stus = new HashSet<Student>();

    /**
    *无参构造方法
    */
    public Course() {

    }

    /**
    *有参构造方法
    */
    public Course(String courseName, String teacher, String classroom) {
        this.courseName = courseName;
        this.teacher = teacher;
        this.classroom = classroom;
    }  

    @Id  //声明了该实体的标识属性,该属性对应表中的主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) //声明了主键的生成策略为自增长,默认值为GenerationType.AUTO
    @Column(name = "course_id")  //声明了属性到列的映射
    public Integer getCourseId() {
        return courseId;
    }

    public void setCourseId(Integer courseId) {
        this.courseId = courseId;
    }

    @Column(name = "course_name")//声明了属性到列的映射
    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    @Column(name = "c_teacher")//声明了属性到列的映射
    public String getTeacher() {
        return teacher;
    }

    public void setTeacher(String teacher) {
        this.teacher = teacher;
    }

    @Column(name = "c_classroom")//声明了属性到列的映射
    public String getClassroom() {
        return classroom;
    }

    public void setClassroom(String classroom) {
        this.classroom = classroom;
    }

    // mappedBy属性指定关联对象的属性名,表明由对方Order维护关联关系
    @ManyToMany(targetEntity = Student.class, fetch = FetchType.LAZY, mappedBy = "cous", cascade = CascadeType.ALL)
    public Set<Student> getStus() {
        return stus;
    }

    public void setStus(Set<Student> stus) {
        this.stus = stus;
    }

}

3.编写测试文件 DemoManyToMany

package com.zr.test;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.zr.obj.Course;
import com.zr.obj.Student;
import com.zr.util.HibernateSessionFactory;

public class DemoManyToMany {
    public static void main(String[] args) {
        save();
        System.out.println("操作成功!!!");
    }

    public static void save() {

        Session session = HibernateSessionFactory.getSession();//建立会话工厂,获得会话!

        Transaction t = session.beginTransaction();// 事务。事务的四大特性:原子性,一致性,隔离性,持久性

        Course c1 = new Course("大学高数", "张老师", "101室");
        Course c2 = new Course("大学英语", "朱老师", "122室");
        Course c3 = new Course("体育", "唐老师", "221室");

        Student s1 = new Student("朱振德", "男", "22");
        Student s2 = new Student("唐婧", "女", "18");

        //建立s1与c1、c2的关联关系
        s1.getCous().add(c1);
        s1.getCous().add(c2);
        s1.getCous().add(c3);

        //建立s2与c2、c3的关联关系
        s2.getCous().add(c2);
        s2.getCous().add(c3);

        //由于Student控制关联关系,保存Student实体即可
        session.save(s1);
        session.save(s2);

        t.commit();
        session.close();

    }
}

4.配置文件

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>

    <session-factory>
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <property name="connection.url">
            jdbc:mysql://localhost:3306/meitao
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <property name="myeclipse.connection.profile">mysql</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

        <mapping class="com.zr.obj.Student" />
        <mapping class="com.zr.obj.Course" />
    </session-factory>

</hibernate-configuration>

5.知识点汇总

  • 如果没有在属性上添加@Column,则表明该属性所映射字段的名称与其同名 注解既可放在属性上,也可放在属性的getter方法上。

  • cascade指定对关联实体所采用的级联策略,该级联策略支持如下五个属性值:
    CascadeType.ALL包含所有;
    CascadeType.PERSIST只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态)
    CascadeType.MERGE指A类新增或者变化,会级联B对象(新增或者变化)
    CascadeType.REFRESH级联保存:当多个用户同时作操作一个实体,为了用户取到的数据是实时的,在用实体中的数据之前就可以调用一下refresh()方法

  • 指定抓取关联实体时的抓取策略,该属性支持以下两个属性值:
    FetchType.EAGER:抓取实体时,立即抓取关联实体,这是默认值
    FetchType.LAZY:抓取实体时,延迟抓取关联实体,等到真正用到关联实体时才去抓取

  • hibernate 之所以提供与save()功能几乎完全类似的persist()方法,一方面是为了照顾JPA的用法习惯。
    另一方面,save()和 persist()方法还有一个区别: 使用 save()
    方法保存持久化对象时,该方法返回该持久化对象的标识属性值(即对应记录的主键值); 但使用 persist()
    方法来保存持久化对象时,该方法没有任何返回值。 因为 save() 方法需要立即返回持久化对象的标识属性,所以程序执行 save()
    会立即将持久化对象对应的数据插入数据库; 而 persist() 则保证当它在一个事物外部被调用时,并不立即转换成 insert 语句,
    这个功能是很有用的,尤其当我们封装一个长会话流程的时候,persist() 方法就显得尤为重要了。

    主要内容区别:
    1,persist把一个瞬态的实例持久化,但是并”不保证”标识符(identifier主键对应的属性)被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时候。
    2,save, 把一个瞬态的实例持久化标识符,及时的产生,它要返回标识符,所以它会立即执行Sql insert

  • @JoinTable属性说明
    name 指定连接表(中间关系表)的表名
    joinColumns 该属性可以接受多个@JoinColumn,用于配置连接表中外键列的列信息,这些外键列参照当前实体的主键列
    inverseJoinColumns 该属性可以接受多个@JoinColumn,用于配置连接表中外键列的列信息,这些外键列参照当前实体的关联实体的主键列

6.小秘籍

  • 多对多,两个实体类都要定义对方实体类的集合属性

  • 控制关联关系的一端,配置注解
    @ManyToMany(fetch = FetchType.LAZY, targetEntity = Course.class, cascade = CascadeType.ALL)
    @JoinTable(name = “stu_cou”, joinColumns = { @JoinColumn(name = “student_id”) }, inverseJoinColumns = {@JoinColumn(name = “course_id”) })

    不控制关联关系的一端,配置注解
    @ManyToMany(targetEntity = Student.class, fetch = FetchType.LAZY, mappedBy = “cous”, cascade = CascadeType.ALL)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值