Hibernate5.2关联关系之单向一对多(一)

Hibernate5.2之单向一对多

一. 简介

     Hibernate中最复杂的应该就是各种关联(单向一对多、单向多对一、双向一对多、一对一、多对多)关系的映射,于是笔者就想着去写一些关于Hibernate相关的系列文章,可能最近今年项目上基本上没怎么用Hibernate,包括身边的很多人都在唱衰Hibernate,觉得他笨重、低效,但是笔者认为这都不影响其在我心目中的地位,以及他当初给笔者所带来的震撼,也影响千千万万的程序员。本系列博客中没有关于Hibernate原理性的东西的讲解,只是一些基本的示例,其实经验稍微丰富一点的程序员其实也能够想象的到其底层的一个实现原理。此篇文章为Hibernate系列的第一篇,在第二节中所创建的基础代码会贯穿着整个系列文章,在后续的博客中笔者将不在作任何的赘述。而关于第三节的数据库的创建会贯穿着一对多、HQL查询、SQL查询、QBC查询系列篇章,故在这些相关篇章中笔者将会依然使用此处所创建的数据库。本系列教程中所使用的数据库为Oracle,Hibernate的版本为5.2.0。

二. 基础代码的创建

2.1 Session工具类

public class OracleSessionUtils {
    //获取SessionFactory
    public static SessionFactory getSessionFactory(){
        StandardServiceRegistry registry = null;
        SessionFactory sessionFactory = null;
        try{
            registry = new StandardServiceRegistryBuilder().configure("hibernate-oracle.xml").build();
            sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
        }catch(Exception ex){
            ex.printStackTrace();
            StandardServiceRegistryBuilder.destroy(registry);
        }
        return sessionFactory;
    }

    //打开并返回一个Session
    public static Session openSession(){
        return getSessionFactory().openSession();
    }

    //关闭Session
    public static void closeSession(Session session){
        if(null != session){
            session.close();
        }
    }
}

2.2 基础单元测试代码

public class HibernateTest {
    private Session session;

    @Before
    public void openSession(){
        session = OracleSessionUtils.openSession(); //打开会话
    }

    @After
    public void closeSession(){
        OracleSessionUtils.closeSession(session);
    }
}

三. 数据库的创建

create table CUSTOMER
(
  id           NUMBER(10) not null,
  name         VARCHAR2(255 CHAR),
  phone_number VARCHAR2(255 CHAR),
  primary key (ID)
);
create table ORDERS
(
  id          NUMBER(10),
  order_id    VARCHAR2(255 CHAR),
  create_time TIMESTAMP(6),
  customer_id NUMBER(10),
  primary key (ID)
);

四. hbm文件的方式

 4.1 POJO类的创建

public class Customer {
    private int id;
    private String name;
    private String phoneNum;
    private Set<Order> orderSet;
    //setter and getter
}

public class Order {
    private int id;
    private String orderId;
    private Date createTime;
    //setter and getter
}

4.2 hbm文件的创建

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>
    <class name="com.demo.hibernate.one2many.Customer" table="customer">
        <id name="id" type="int">
            <generator class="sequence">
                <param name="sequence">cus_order_seq</param>
            </generator>
        </id>
        <property name="name" type="string" column="name"></property>
        <property name="phoneNum" type="string" column="phone_number"></property>
        <set name="orderSet">
            <key column="customer_id"></key>
            <one-to-many class="com.demo.hibernate.one2many.Order"/>
        </set>
    </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>
    <class name="com.demo.hibernate.one2many.Order" table="orders">
        <id name="id" type="int">
            <generator class="sequence">
                <param name="sequence">cus_order_seq</param>
            </generator>
        </id>
        <property name="orderId" column="order_id" type="string"></property>
        <property name="createTime" column="create_time" type="timestamp"></property>
    </class>
</hibernate-mapping>

五.注解的方式

  注解的方式已经逐渐替代了以前的XML文件配置的方式,摈弃了以往每修改一次POJO类就必须修改XML文件的繁琐的方式。注:注解可以放在成员变量的上面,也可以放在对应的get方法上面。

Customer.java

@Entity
@Table(name="customer")
public class Customer {
    @Id
    @Column(name="id")
    @GenericGenerator(name="sequenceGenerator", strategy="sequence", parameters={@Parameter(name="sequence", value="cus_order_seq")})
    @GeneratedValue(generator="sequenceGenerator")
    private int id;

    @Column(name="name")
    private String name;

    @Column(name="phone_number")
    private String phoneNum;

    @OneToMany
    @JoinColumn(name="customer_id")
    private Set<Order> orderSet;

    //setter and getter
}

Order.java

@Entity
@Table(name="orders")
public class Order {
    @Id
    @Column(name="id")
    @GenericGenerator(name="sequenceGenerator", strategy="sequence", parameters={@Parameter(name="sequence", value="cus_order_seq")})
    @GeneratedValue(generator="sequenceGenerator")
    private int id;

    @Column(name="order_id")
    private String orderId;

    @Column(name="create_time")
    @Type(type="timestamp")
    private Date createTime;

    //setter and getter
}

六. 代码测试

A.保存

@Test
public void save(){
    Transaction tx = session.beginTransaction();
    Customer customer = new Customer();
    customer.setName("AAAAA");
    customer.setPhoneNum("334411");

    Order order = new Order();
    order.setCreateTime(new Date());
    order.setOrderId("A");

    Order order1 = new Order();
    order1.setCreateTime(new Date());
    order1.setOrderId("B");

    Set<Order> orderSet = new HashSet<Order>();
    orderSet.add(order);
    orderSet.add(order1);

    customer.setOrderSet(orderSet);
    session.save(customer);
    session.save(order);
    session.save(order1);
    tx.commit();
}

B.get查询

@Test
public void get(){
    Customer customer = session.get(Customer.class, 42);
    System.out.println("查询Customer的SQL已经发送");
    System.out.println(customer.getPhoneNum() + "::" + customer.getName());
    Set<Order> set = customer.getOrderSet();
    System.out.println("查询Order的SQL还未发送,因为延迟加载,只有当在使用Order的时候才会发送SQL");
    for(Order o : set){
        System.out.println(o.getOrderId() + "::" + o.getCreateTime());
    }
}

C.load查询

@Test
public void load(){
    Customer customer = session.load(Customer.class, 42);
    System.out.println("查询Customer的SQL还未发送,只有当使用的时候才会放松SQL");
    System.out.println(customer.getPhoneNum() + "::" + customer.getName());
    Set<Order> set = customer.getOrderSet();
    System.out.println("查询Order的SQL还未发送,因为延迟加载,只有当在使用Order的时候才会发送SQL");
    for(Order o : set){
        System.out.println(o.getOrderId() + "::" + o.getCreateTime());
    }
}

D.删除

@Test
public void delete(){
    Customer customer = new Customer();
    customer.setId(42);
    /* 如果设置了Order则会先执行更新
    Order order = new Order();
    order.setId(43);
    Order order1 = new Order();
    order1.setId(44);
    Set<Order> orderSet = new HashSet<Order>();
    orderSet.add(order);
    orderSet.add(order1);
    customer.setOrderSet(orderSet);
    */
    Transaction tx = session.beginTransaction();
    session.delete(customer);
    tx.commit();
}

E.更新

@Test
public void update(){
    Customer customer = new Customer();
    customer.setId(45);  //如果没有设置Id会报错
    customer.setName("BBBNNN");
    customer.setPhoneNum("990088");

    Order order = new Order();
    order.setId(46);   //如果没有Id则会执行插入
    order.setCreateTime(new Date());
    order.setOrderId("N");

    Order order1 = new Order();
    order1.setId(47); //如果没有Id则会执行插入
    order1.setCreateTime(new Date());
    order1.setOrderId("G");

    Set<Order> orderSet = new HashSet<Order>();
    orderSet.add(order);
    orderSet.add(order1);
    //如果Customer中设置了Order,会先将Order表的customer_id置空,然后再更新customer_id
    //但是不会更新其他的数据
    customer.setOrderSet(orderSet);  

    Transaction tx = session.beginTransaction();
    session.update(customer);
    tx.commit();
}
时间: 2024-10-06 22:40:28

Hibernate5.2关联关系之单向一对多(一)的相关文章

Hibernate5.2关联关系之单向多对一(二)

Hibernate5.2之单向一对多(二) 一. 简介 在本篇博文中笔者会在上一篇博客的代码基础上进行修改,本篇文章将介绍单向的一对多. 二. hbm文件的方式 Customer.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

Hibernate5.2关联关系之双向一对多(三)

                                                       Hibernate之双向一对多(三) 一.简介 本篇博文接着上一章的内容接着开展,代码也是在上篇博文的基础上修改. 二.hbm文件的方式 Customer.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hi

7、单向一对多的关联关系(1的一方有n的一方的集合属性,n的一方却没有1的一方的引用)

单向一对多的关联关系 关联特点:1的一方有n的一方的集合属性,n的一方却没有1的一方的引用 比如:Customer对Order是一对多的关联关系,则Customer中有Order的集合属性,而Order中却没有对Customer的引用.这样可以通过客户检索到其所有的订单信息,却不能够由订单得到其所属的客户. 映射单向一对多的关联关系有两个要点: 1.利用@OneToMany注解进行单向一对多的映射: 2.利用@JoinColumn来映射外键列的名称: 注意的点: 1.@OneToMany的默认检

JPA 单向一对多关联关系

映射单向一对多的关联关系 1.首先在一的一端加入多的一端的实体类集合 2.使用@OneToMany 来映射一对多的关联关系3.使用@JoinColumn 来映射外键列的名称4.可以使用@OneToMany的fetch 属性来修改默认的加载策略5.可以通过@OneToMany的cascade 属性来修改默认的删除策略6.cascade={CascadeType.REMOVE} 会把主表和从表的数据都删除 如下代码: /** *数据库持久化类 * @author z * */ @Table(name

(十一)Hibernate中的多表操作(1):单向一对多

一.单向一对多() 案例一(用XML文件配置): 一个会员(Member)可以有多个订单(Order),加载会员的时候自动加载订单,但是订单无法查看会员信息, public class Member { private String id; private String name; private Integer age; private Set<Order> orders = new HashSet<Order>(); //该Set集合里存放的是"多"方,加载

Hibernate关联关系映射(单向篇)

Hibernate关联关系可分为单向关联和双向关联两大类.单向关联可以分为一对一.一对多.多对一和多对多4种关联方式,而多向关联可以分为一对一.一对多和多对多3种关联方式. Hibernate连接管理类HibernateUtil.java public class HibernateUtil { private static SessionFactory sessionFactory; private static final ThreadLocal<Session> threadLocal

Hibernate单向“一对多”关联

1. 基于连接表的单向"一对多"关联,应该优先被采用其中指定many-to-many的unique="true",为单向"一对多",不指定就是单向"多对多" <class name="Person">    <id name="id" column="personId"><generator class="native"

hibernate5(10)注解映射[2]一对多单向关联

在上一篇文章里.我们从端方向一端建立关联关系,完毕了从文章到作者的关联关系建立.但在实际的博客站点中,用户肯定还须要获取自己所写的文章,这时能够建立用户(一)对文章(多)的单向关联映射. 先来看我们的一方配置实例 package com.zeng.model; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.F

hibernate5(9)注解映射[1]一对多单向关联

一对多单向关联映射 在实际的博客网站中,用户肯定需要获取自己所写的文章,这时可以建立用户(一)对文章(多)的单向关联映射. 先来看我们的一方配置实例 package com.zeng.model; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persisten