【Hibernate学习笔记】6:单向N-1关联关系的使用demo

Hibernate的一个优势就是处理关联关系时比单纯使用JDBC更方便。

单向N-1关联如N个学生对应一个班主任,这时需要在学生(N的一方)表中添加所属的班主任的字段。因为从班主任表中并不清楚班主任带了哪些学生,所以是学生向班主任的单向关联

POJO类

Student.java

注意通常在持久化类中将时间日期类型设置为java.util.Date,而不是它的子类java.sql.Date,然后在hbm映射文件中type="date"即可,这个Hibernate映射类型是连接两种日期的桥梁。

package myPOJO;

import java.io.Serializable;
import java.util.Date;

//学生POJO类
public class Student implements Serializable {
    private Integer id;// 逻辑主键
    private String stuNo;// 学生学号
    private String stuName;// 学生姓名
    private Date dtIn;// 入学时间
    private Teacher tchr;// 班主任,Techer对象的引用

    // 无参构造器
    public Student() {

    }

    // 有参构造器,不要提供逻辑主键
    public Student(String stuNo, String stuName, Date dtIn, Teacher tchr) {
        this.stuName = stuName;
        this.stuNo = stuNo;
        this.dtIn = dtIn;
        this.tchr = tchr;
    }

    // getter和setter

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getStuNo() {
        return stuNo;
    }

    public void setStuNo(String stuNo) {
        this.stuNo = stuNo;
    }

    public Date getDtIn() {
        return dtIn;
    }

    public void setDtIn(Date dtIn) {
        this.dtIn = dtIn;
    }

    public Teacher getTchr() {
        return tchr;
    }

    public void setTchr(Teacher tchr) {
        this.tchr = tchr;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
}
Teacher.java
package myPOJO;

import java.io.Serializable;

//教师POJO类
public class Teacher implements Serializable {
    private Integer id;// 逻辑主键
    private String tchrNo;// 教师工号
    private String tchrName;// 教师姓名
    private Integer mny;// 月收入

    // 无参构造器
    public Teacher() {
    }

    // 有参构造器,不要提供逻辑主键
    public Teacher(String tchrNo, String tchrName, Integer mny) {
        this.tchrNo = tchrNo;
        this.tchrName = tchrName;
        this.mny = mny;
    }

    // getter和setter

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTchrNo() {
        return tchrNo;
    }

    public void setTchrNo(String tchrNo) {
        this.tchrNo = tchrNo;
    }

    public String getTchrName() {
        return tchrName;
    }

    public void setTchrName(String tchrName) {
        this.tchrName = tchrName;
    }

    public Integer getMny() {
        return mny;
    }

    public void setMny(Integer mny) {
        this.mny = mny;
    }

}

映射文件

和对应的POJO类放在一个路径下。

Student.hbm.xml

在单向N-1关联中的N方的POJO类需要组合1方的引用,并且需要在N方的映射文件中使用<many-to-one>标签配置N-1关联关系。

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--指出包名,也可以不指出而在后面使用包名.类名 -->
<hibernate-mapping package="myPOJO">
    <!--指出类名(如果前面没有指出包名,这里需要包名.类名),映射到的数据库中的表名 -->
    <class name="Student" table="StudentTable">

        <!--主键的名称,对应于数据库表中的字段名,类型 -->
        <id name="id" column="ID" type="int">
            <!--主键生成器,指定生成策略,native则由Hibernate根据DBMS自选 -->
            <generator class="native" />
        </id>

        <!--非主属性(学号):属性名,对应表中字段名,类型,是否非空 -->
        <property name="stuNo" column="STUNO" type="string" not-null="true" />
        <!--还可以这样写(姓名) -->
        <property name="stuName" type="string" not-null="true">
            <column name="STUNAME" />
        </property>
        <!--非主属性(入学时间):属性名,对应表中字段名,类型,是否非空 -->
        <property name="dtIn" column="DATEIN" type="date" not-null="true" />

        <!--N-1映射(班主任):属性名,对应表中字段名,所引用的类的类名 ,是否非空,级联策略-->
        <many-to-one name="tchr" column="TEACHER_ID" class="Teacher" not-null="false" cascade="all"/>

    </class>
</hibernate-mapping>
Teacher.hbm.xml

单向N-1映射中的1方不需要对该映射做任何改动和配置。

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--指出包名,也可以不指出而在后面使用包名.类名 -->
<hibernate-mapping package="myPOJO">
    <!--指出类名(如果前面没有指出包名,这里需要包名.类名),映射到的数据库中的表名 -->
    <class name="Teacher" table="TeacherTable">

        <!--主键的名称,对应于数据库表中的字段名,类型 -->
        <id name="id" column="ID" type="int">
            <!--主键生成器,指定生成策略,native则由Hibernate根据DBMS自选 -->
            <generator class="native" />
        </id>

        <!--非主属性(工号):属性名,对应表中字段名,类型,是否非空 -->
        <property name="tchrNo" column="TCHRNO" type="string" not-null="true" />
        <!--还可以这样写(姓名) -->
        <property name="tchrName" type="string" not-null="true">
            <column name="TCHRNAME" />
        </property>
        <!--非主属性(月收入):属性名,对应表中字段名,类型,是否非空 -->
        <property name="mny" column="MONEY" type="int" not-null="false" />

        <!--单向N-1映射中的1方不需要对该映射做任何改动和配置-->

    </class>
</hibernate-mapping>

DAO类

通过数据访问类中的静态方法来对PO进行数据操作,更加OOP和方便。

StudentDAO.java
package myDAO;

import myPOJO.Student;
import myTools.HibernateUtils;

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

//Student类POJO的数据访问类,使用了Hibernate工具类
public class StudentDAO {

    // 在数据库中添加一个Student
    public static void addStudent(Student stu) {
        // 获取Session对象
        Session sssn = HibernateUtils.getSession();
        // 开启事务
        Transaction trnsctn = sssn.beginTransaction();
        // 保存持久化对象
        sssn.save(stu);
        // 提交事务
        trnsctn.commit();
        // 关闭Session实例并且把ThreadLocal中的副本清除
        HibernateUtils.closeSession();
    }

    // 其它操作...
}
TeacherDAO.java
package myDAO;

import myPOJO.Teacher;
import myTools.HibernateUtils;

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

//Teacher类POJO的数据访问类,使用了Hibernate工具类
public class TeacherDAO {

    // 在数据库中添加一个Teacher
    public static void addTeacher(Teacher tchr) {
        // 获取Session对象
        Session sssn = HibernateUtils.getSession();
        // 开启事务
        Transaction trnsctn = sssn.beginTransaction();
        // 保存持久化对象
        sssn.save(tchr);
        // 提交事务
        trnsctn.commit();
        // 关闭Session实例并且把ThreadLocal中的副本清除
        HibernateUtils.closeSession();
    }

    // 其它操作...
}

配置文件

key-value的配置文件没改,只在xml配置文件中更改了注册映射。

hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- Hibernate配置文件 -->
<!-- 为了方便,在这里只做了注册映射文件的事情 -->
<!-- 另外的一些配置以key=value的形式写在hibernate.properties里 -->
<hibernate-configuration>
    <session-factory>
        <!-- 注册Student类的ORM映射文件 -->
        <mapping resource="myPOJO/Student.hbm.xml" />
        <!-- 注册Teacher类的ORM映射文件 -->
        <mapping resource="myPOJO/Teacher.hbm.xml" />
    </session-factory>
</hibernate-configuration>

主类

import java.util.Date;

import myDAO.StudentDAO;
import myDAO.TeacherDAO;
import myPOJO.Student;
import myPOJO.Teacher;

//测试学生到班主任的N-1关系映射
public class Main {

    // 主方法
    public static void main(String[] args) {
        // 添加一个老师
        System.out.println("----添加一个老师作为班主任----");
        Teacher tchr = new Teacher("T0001", "大司马", 500);
        TeacherDAO.addTeacher(tchr);

        // 添加两个该老师的学生,学生对老师是单向N-1关系
        System.out.println("----为该老师添加两个学生----");
        Student stu1 = new Student("S0001", "刘知昊", new Date(), tchr);
        StudentDAO.addStudent(stu1);
        Student stu2 = new Student("S0002", "刘傻逼", new Date(), tchr);
        StudentDAO.addStudent(stu2);

        System.out.println("----操作已经全部执行完,可以查看数据库了----");
    }

}

运行结果

控制台输出
----添加一个老师作为班主任----
Hibernate: insert into TeacherTable (TCHRNO, TCHRNAME, MONEY) values (?, ?, ?)
----为该老师添加两个学生----
Hibernate: insert into StudentTable (STUNO, STUNAME, DATEIN, TEACHER_ID) values (?, ?, ?, ?)
Hibernate: update TeacherTable set TCHRNO=?, TCHRNAME=?, MONEY=? where ID=?
Hibernate: insert into StudentTable (STUNO, STUNAME, DATEIN, TEACHER_ID) values (?, ?, ?, ?)
Hibernate: update TeacherTable set TCHRNO=?, TCHRNAME=?, MONEY=? where ID=?
----操作已经全部执行完,可以查看数据库了----
查看数据库

这里写图片描述

这里写图片描述

尝试删除

删除Teacher表中受Student表使用的行时,会被禁止。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值