Hibernate多表映射之多对一

多表映射之多对一(many-to-one)

在此以员工和部门的关系为例,员工与部门的关系是典型的多对一关系。
员工实体类:

public class Employee {

    private int id;
    private String name;
    private Date birthday;
    private Department department;

    public Employee() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Employee(String name, Date birthday, Department department) {
        super();
        this.name = name;
        this.birthday = birthday;
        this.department = department;
    }
    //...省略getter和setter方法
    }

员工的映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-5-18 15:46:21 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.walter.vo.Employee" table="EMPLOYEE">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="birthday" type="date">
            <column name="BIRTHDAY" />
        </property>
        <!--
            many-to-one:声明当前类对应的表与目标类对应的表之间是多对一的关系
            name:一的一方(Department)在多的一方(Employee)的实体类中对应的属性名,也是当前类对应表中默认的外键字段,默认外键关联的是department表的主键
            class:一的一方(Department)实体类的类路径
            fetch:表示抓取策略,fetch="join"表示使用左链接方式查询
        -->
        <many-to-one name="department" class="com.walter.vo.Department" fetch="join">
            <column name="DEPARTMENT" />
        </many-to-one>
    </class>
</hibernate-mapping>

部门实体类

public class Department {

    private int id;
    private String name;
    //...省略构造方法和getter/setter方法
    }

部门映射文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2017-5-18 15:46:21 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.walter.vo.Department" table="DEPARTMENT">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
    </class>
</hibernate-mapping>

实体类和映射文件配置完成后记得要在Hibernate核心配置文件中配置映射文件。
测试

  • 工具类
public class HibernateUtil {

    private static SessionFactory sessionFactory;
    static{
        Configuration configuration = new Configuration();
        configuration.configure();
        sessionFactory = configuration.buildSessionFactory();
    }

    public static SessionFactory getSessionFactory(){
        return sessionFactory;
    }
    public static Session getSession(){
        return sessionFactory.openSession();
    }
    public static void close(Session s){
        if(s!=null)
            s.close();
    }
}
  • 测试类
    /**
     * 增加数据
     */
    public static void save(){
        Session session = HibernateUtil.getSession();
        Transaction transaction = session.beginTransaction();
        // 创建一个部门对象
        Department department = new Department("技术部");
        // 创建一个员工对象,同时告知该员工对象属于哪个部门。如果在此没有设置employee的department,则该员工的外键值为null
        Employee employee = new Employee("张三", new Date(), department);
        Employee employee2 = new Employee("李四", new Date(), department);

        /*
            如果先保存一的一方(departnment),在保存多的一方(employee),只有insert语句产生。其原理是:
            先保存department,department表中的主键会自动生成,然后在保存employee的时候,会自动引用department中相应的主键
        */
        session.save(department);
        session.save(employee);
        session.save(employee2);
        /*
            如果先保存多的一方(employee),再保存保存一的一方(departnment),除了产生insert语句,还会在insert语句后面产生update语句。其原理是:
            当我们保存员工时,由于还没有保存部门,所以员工的外键没有部门的主键可以引用,所以为null;当我们保存完部门后,会根据部门的主键对相应员工的外键进行更新操作。
        */
        session.save(employee);
        session.save(employee2);
        session.save(department);

        transaction.commit();
        HibernateUtil.close(session);
    }

    /**
     * 根据id查询数据
     */
    public static Employee getById(int id){
        Session session = HibernateUtil.getSession();
        Employee employee = (Employee) session.get(Employee.class, 1);
        /*初始化代理对象:
            Hibernate.initialize(employee.getDepartment());
        */
        HibernateUtil.close(session);
        return employee;
    }

    public static void main(String[] args){
        Employee employee = getById(1);
        System.out.println(employee.getName());//此时name可以正常输出       
        /*下面代码回报错,错误信息是:Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session.
        说明在查询雇员时默认情况下是不查询部门的,当前查询部门时session已经关闭了,才报上面的错误。
         结论:在多对一关联映射中,默认情况下对一的加载时存在延迟(懒)加载的。
         解决延时加载有两种办法:
             1.初始化代理对象:
             ibernate.initialize(employee.getDepartment());
             2.在多的一方的<many-to-one>标签中配置属性lazy="false"或者fetch="join"
        */
        System.out.println(employee.getDepartment()
        .getName);

在此主要介绍了Hibernate中多表映射的一种,在后续文章中会继续介绍其他的映射关系。如果对Hibernate配置文件不是太清楚的小伙伴可以移步到Hibernate笔记一(Hibernate简单配置和操作)来看看。
欢迎大家讨论和指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

记忆旅途

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值