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();
}

下一篇:Hibernate5.2之单向一对多(二)

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

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

    Hibernate5.2之单向一对多(二) 一. 简介 在本篇博文中笔者会在上一篇博客的代码基础上进行修改,本篇文章将介绍单向的一对多. 二. hbm文件的方式 Customer.hbm.xml &l ...

  2. JPA(六):映射关联关系------映射单向一对多的关联关系

    映射单向一对多的关联关系 新建项目项目请参考<JPA(二):HellWord工程>,基于上一章讲解的<JPA(五):映射关联关系------映射单向多对一的关联关系>中的例子进 ...

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

                                                           Hibernate之双向一对多(三) 一.简介 本篇博文接着上一章的内容接着开展,代码也是 ...

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

    单向一对多的关联关系 具体体现:1的一方有n的一方的集合的引用,n的一方却没有1的一方的引用 举个例子:顾客Customer对订单Order是一个单向一对多的关联关系.Customer一方有对Orde ...

  5. JPA 单向一对多关联关系

    映射单向一对多的关联关系 1.首先在一的一端加入多的一端的实体类集合 2.使用@OneToMany 来映射一对多的关联关系3.使用@JoinColumn 来映射外键列的名称4.可以使用@OneToMa ...

  6. JPA中实现单向一对多的关联关系

    场景 JPA入门简介与搭建HelloWorld(附代码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103473937 ...

  7. Hibernate(7)关联关系_单向1对n

    1.单向一对多(@OneToMany)关联是比较少用的(一般用双向一对多代替). 2.实体类: 1端:Publishers.java public class Publishers { private ...

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

    一.单向一对多() 案例一(用XML文件配置): 一个班级有多个学生,班级可以查看所有学生的信息. ClassBean.java package bean; import java.util.Hash ...

  9. jpa单向一对多

    单向一对多是一个类中的一条记录可对应另一个类的多条记录: 比如一个部门可对应多个员工:   jpa中的实现步骤:     one-to-many的one类中添加一个many类类型的set;比如部门类D ...

随机推荐

  1. Educational Codeforces Round 14 D. Swaps in Permutation

    题目链接 分析:一些边把各个节点连接成了一颗颗树.因为每棵树上的边可以走任意次,所以不难想出要字典序最大,就是每棵树中数字大的放在树中节点编号比较小的位置. 我用了极为暴力的方法,先dfs每棵树,再用 ...

  2. MongoDB整库备份与还原以及单个collection备份、恢复方法

    mongodb数据库维护离不开必要的备份.恢复操作,而且一般不会出错,所以我们在使用的时候大部分时候使用备份和恢复操作就可以了   mongodump.exe备份的原理是通过一次查询获取当前服务器快照 ...

  3. Android开发--RadioButton的应用

    1.简介 RadioButton为单选按钮,当一个按钮被选中后,点击其他按钮无法使上一个按钮变为未选中状态.RadioGroup是可以容纳多个RadioButton的容器, 通过使用RadioGrou ...

  4. WinForm程序打包说明

    如果使用的是VS2013需要下载并安装 Microsoft Visual Studio 2013 Installer Projects 下载地址:https://visualstudiogallery ...

  5. iOS开发拓展篇—CoreLocation地理编码

    iOS开发拓展篇—CoreLocation地理编码 一.简单说明 CLGeocoder:地理编码器,其中Geo是地理的英文单词Geography的简写. 1.使用CLGeocoder可以完成“地理编码 ...

  6. c# 配置文件之configSections配置(二)

    在很多时候我们需要自定义我们自己的自定义App.config 文件,而微软为我们提供了默认的 System.Configuration.DictionarySectionHandler System. ...

  7. 【61测试】【dp】【二分】【前缀和】【树剖】

    不要问我为什么昨天考的今天才贴解题报告.. 第一题: 给定3个字符串,求它们的最长公共子序列. 解: 考试时知道肯定是LCS的二维再加一维,用三维,可天堂有路你不走,地狱无门你偏来...灵机一动想出来 ...

  8. [HB2014 Week5] Allot 人员分配

    这两天决心专门搞好网络流了 - - 题解在什么瞎胡搞跟我说要连n+2和n+1容量为无穷的边…我看了下std才做的… 坑死人的地方就是,需要求多次网络流,每次别忘了把流给清空了…这次是用链表所以专门写了 ...

  9. servlet执行流程

    视频地址:http://www.imooc.com/video/5550      1-6 用户输入地址:localhost:8080/MyFirstServletDemo/index.jsp (My ...

  10. 例子:Alarm Clock with voice Commands Sample

    通过本例子学习: 如何使用自定义字体文件(.TTF) 如何播放声音 动画的使用 Speech 设置闹铃 应用 设置 数据存储到IsolatedStorage 如何使用自定义字体文件(.TTF) < ...