Hibernate学习笔记 | 详解映射关系(一对一、一对多、多对多、继承关系)

映射一对多关联关系

  • 在领域模型中,类与类之间最普遍的关系就是关联关系。
  • 在UML中,关联是有方向的。
    CustomerOrder为例:一个用户能发出多个订单,而一个订单只能属于一个客户,从OrderCustomer的关联是多对一的关联,而从CustomerOrder是一对多的关联。

单向n-1

  • 单向n-1关联只需从n端可以访问1端。
  • 域模型:从OrderCustomer的多对一单向关联需要在Order类中定义一个Customer属性,而在Customer类中无需定义存放Order对象的集合属性。
  • 关系数据模型:orders表中的customer_id参照customer表的主键。
  • 在Hibernate映射文件中使用<many-to-one>标签可以来映射多对一的关联关系,其标签有如下属性:
    name:一的那一端的属性的名字
    class:一的那一端对应的类名
    column:一的那一端在多的一端中对应的数据表中的外键的名字

在此以Order和Customer为例,Order与Customer为多对一关系。首先我们建立Order类和Customer类,如下:

package com.cerr.hibernate.n21;
public class Order {
    private Integer orderId;
    private String orderName;
    private Customer customer;
    public Integer getOrderId() {
        return orderId;
    }
    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }
    public String getOrderName() {
        return orderName;
    }
    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }
    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}
package com.cerr.hibernate.n21;
public class Customer {
    private Integer customerId;
    private String customerName;
    public Integer getCustomerId() {
        return customerId;
    }
    public void setCustomerId(Integer customerId) {
        this.customerId = customerId;
    }
    public String getCustomerName() {
        return customerName;
    }
    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }
}

IDEA只支持由数据表映射出实体类和映射文件,而我们此时是要通过实体类和映射文件来生成数据表,因此映射文件应该我们自己来新建。因此我们新建Customer.hbm.xml文件和Order.hbm.xml文件。映射信息如下:
Customer.hbm.xml文件:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!--加入select-before-update="true" -->
    <class name="com.cerr.hibernate.n21.Customer" table="customers" schema="hibernate5" dynamic-update="true">
        <id name="customerId" column="customer_id">
            <generator class="native" />
        </id>
        <property name="customerName" column="customer_name"/>

    </class>
</hibernate-mapping>

Order.hbm.xml文件:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!--加入select-before-update="true" -->
    <class name="com.cerr.hibernate.n21.Order" table="orders" schema="hibernate5" dynamic-update="true">
        <id name="orderId" column="order_id">
            <generator class="native" />
        </id>
        <property name="orderName" column="order_name"/>

        <!-- 映射多对一的关联关系 -->
        <many-to-one name="customer" class="com.cerr.hibernate.n21.Customer" column="customer_id"></many-to-one>

    </class>
</hibernate-mapping>

保存操作的测试类:

package com.cerr.hibernate.n21;

import com.cerr.hibernate.helloworld.News;
import com.cerr.hibernate.helloworld.Pay;
import com.cerr.hibernate.helloworld.Worker;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.junit.After;
import org.junit.Before;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

public class Test {
    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;

    @Before
    public void init() throws Exception {
        Configuration configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @After
    public void destory() throws Exception {
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
    @org.junit.Test
    public void test4(){
        Customer customer = new Customer();
        customer.setCustomerName("aa");
        Order order = new Order();
        order.setOrderName("1");
        Order order1 = new Order();
        order1.setOrderName("2");
        //设定关联关系
        order.setCustomer(customer);
        order1.setCustomer(customer);
        //先插入1的一端,再插入n的一端。只有三条insert语句。
        session.save(customer);
        session.save(order);
        session.save(order1);
        //如果先插入n的一端,再插入1的一端,则会多出来num(n的一端)条update语句。
//        session.save(order);
//        session.save(order1);
//        session.save(customer);
    }
    }

在测试类中我们分别新建了两个Order类和一个Customer类,并且在调用save()时我们使用了两种情况,一种情况是先保存Customer类(即先保存1),再保存Order类(再保存n)。另一种是先保存Order类(先保存n),再保存Customer类(再保存1)。两种结果都会插入成功,但是第一种的话只会生成3条INSERT语句,但是第二种会生成3条INSERT语句和2条UPDATE语句。因为先插入n的一端时,无法确定1的一端的外键值,所以只能先进行插入,然后等1的一端插入之后,再额外的发送UPDATE去修改n的一端的外键属性。
所以在插入的时候我们推荐先插入1的那一端,再插入n的那一端。
生成的数据表如下:

13424350-a7d7b29a2d462300.png
customers数据表

13424350-5635bdd0b8dce144.png
orders数据表

查询操作的测试类:

package com.cerr.hibernate.n21;

import com.cerr.hibernate.helloworld.News;
import com.cerr.hibernate.helloworld.Pay;
import com.cerr.hibernate.helloworld.Worker;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.junit.After;
import org.junit.Before;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Date;

public class Test {
    private SessionFactory sessionFactory;
    private Session session;
    private Transaction transaction;

    @Before
    public void init() throws Exception {
        Configuration configuration = new Configuration().configure();
        sessionFactory = configuration.buildSessionFactory();
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @After
    public void destory() throws Exception {
        transaction.commit();
        session.close();
        sessionFactory.close();
    }

    @org.ju
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值