Rhythmk 学习 Hibernate 05 - Hibernate 表间关系 [ManyToOne,OneToMany]
1、项目结构:

1.1、场景说明: 一个订单,包含多个产品
1.2、类文件:
Order.java
package com.rhythmk.model;
import java.util.Date;
public class Order {
public int getOrderID() {
return orderID;
}
public void setOrderID(int orderID) {
this.orderID = orderID;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public double getSumMoney() {
return SumMoney;
}
public void setSumMoney(double sumMoney) {
SumMoney = sumMoney;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
private int orderID;
private String Name;
private double SumMoney;
@Override
public String toString() {
return "Order [orderID=" + orderID + ", Name=" + Name + ", SumMoney="
+ SumMoney + ", createDate=" + createDate + "]";
}
private Date createDate;
}
order.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.rhythmk.model.Order" table="t_order">
<id name="orderID" type="int">
<column name="orderID" />
<generator class="native" />
</id>
<property name="Name" type="string">
<column name="Name" not-null="true" />
</property>
<property name="SumMoney" type="double"></property>
<property name="createDate" type="timestamp">
<column name="createDate" not-null="true" />
</property> </class>
</hibernate-mapping>
Product.java
package com.rhythmk.model;
public class Product {
public int getProductID() {
return productID;
}
public void setProductID(int productID) {
this.productID = productID;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
private int productID;
private String productName;
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
private Order order ;
@Override
public String toString() {
return "Product [productID=" + productID + ", productName="
+ productName + ", order=" + order + "]";
}
}
product.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping>
<class name="com.rhythmk.model.Product" table="t_product">
<id name="productID" type="int">
<column name="productID" />
<generator class="native" />
</id>
<property name="productName" type="string">
<column name="productName" />
</property>
<many-to-one name="order" column="orderID"></many-to-one> </class>
</hibernate-mapping>
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration> <session-factory>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate_demo</property>
<property name="connection.username">root</property>
<property name="connection.password">wangkun</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="myeclipse.connection.profile">com.mysql.jdbc.Driver</property>
<!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可以设置为false,提高运行效率 -->
<property name="hibernate.show_sql">true </property>
<property name="hibernate.hbm2ddl.auto">update</property> <mapping resource="com/rhythmk/model/user.hbm.xml" />
<mapping resource="com/rhythmk/model/product.hbm.xml" />
<mapping resource="com/rhythmk/model/order.hbm.xml" />
</session-factory> </hibernate-configuration>
1.3 、结论:
在Many方 定义XML配置 :
<many-to-one name="order" column="orderID"></many-to-one>
写入数据调用session.save方法跟单表保存基本一致。
读取数据:获取Many对象,默认 One对象都是以延迟加载模式进行加载。
不论是删除 Many ,还是删除 One 对象 都只删除本身数据 ,并非删除全部主从数据,如果删除One对象,一旦Many还有关联One的对象的存在,则将抛出异常。见(test04_del)
1.4 、测试验证:
@Test
public void test02_add() {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Order order = new Order();
order.setCreateDate(new Date());
order.setName("订单一");
order.setSumMoney(12);
session.save(order); Product p1 = new Product();
p1.setOrder(order);
p1.setProductName("产品1");
session.save(p1); Product p2 = new Product();
p2.setOrder(order);
p2.setProductName("产品2");
session.save(p2); session.getTransaction().commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null)
session.close();
}
}
输出:
Hibernate: insert into t_order (Name, SumMoney, createDate) values (?, ?, ?)
Hibernate: insert into t_product (productName, orderID) values (?, ?)
Hibernate: insert into t_product (productName, orderID) values (?, ?)
@Test
public void test03_load() {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
Order order = (Order) session.load(Order.class, 1);
System.out.println(order);
System.out.println("-----------Read Product-----------");
Product product = (Product) session.load(Product.class, 1);
System.out.println("-----------Print Product-----------");
System.out.println(product);
System.out.println("-----------Read Order-----------");
System.out.println(product.getOrder().getName()); } catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null)
session.close();
}
}
输出:
Hibernate: select order0_.orderID as orderID1_0_0_, order0_.Name as Name2_0_0_, order0_.SumMoney as SumMoney3_0_0_, order0_.createDate as createDa4_0_0_ from t_order order0_ where order0_.orderID=?
Order [orderID=1, Name=订单一, SumMoney=12.0, createDate=2014-05-02 15:24:02.0]
-----------Read Product-----------
-----------Print Product-----------
Hibernate: select product0_.productID as productI1_1_0_, product0_.productName as productN2_1_0_, product0_.orderID as orderID3_1_0_ from t_product product0_ where product0_.productID=?
Product [productID=1, productName=产品1, order=Order [orderID=1, Name=订单一, SumMoney=12.0, createDate=2014-05-02 15:24:02.0]]
-----------Read Order-----------
订单一
@Test
public void test04_Get() {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession(); System.out.println("-----------Read Product-----------");
Product product = (Product) session.get(Product.class, 1);
System.out.println("-----------Print Product-----------");
System.out.println(product);
System.out.println("-----------Read Order-----------");
System.out.println(product.getOrder().getName()); } catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null)
session.close();
}
}
输出:
-----------Read Product-----------
Hibernate: select product0_.productID as productI1_1_0_, product0_.productName as productN2_1_0_, product0_.orderID as orderID3_1_0_ from t_product product0_ where product0_.productID=?
-----------Print Product-----------
Hibernate: select order0_.orderID as orderID1_0_0_, order0_.Name as Name2_0_0_, order0_.SumMoney as SumMoney3_0_0_, order0_.createDate as createDa4_0_0_ from t_order order0_ where order0_.orderID=?
Product [productID=1, productName=产品1, order=Order [orderID=1, Name=订单一, SumMoney=12.0, createDate=2014-05-02 15:24:02.0]]
-----------Read Order-----------
订单一
@Test
public void test04_Del() {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
/* Product product = (Product) session.get(Product.class, 1);
session.delete(product);
输出:
Hibernate: select product0_.productID as productI1_1_0_, product0_.productName as productN2_1_0_, product0_.orderID as orderID3_1_0_ from t_product product0_ where product0_.productID=?
Hibernate: delete from t_product where productID=?
*/
Order order = (Order) session.get(Order.class, 3);
session.delete(order); session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null)
session.close();
}
}
输出:
Hibernate: select order0_.orderID as orderID1_0_0_, order0_.Name as Name2_0_0_, order0_.SumMoney as SumMoney3_0_0_, order0_.createDate as createDa4_0_0_ from t_order order0_ where order0_.orderID=?
Hibernate: delete from t_order where orderID=?
org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:190)
-------------------------------------------------OneToMany----------------------------------------------------------------------------
>>> OneToMany 单相关联
2.1
需求背景:
每个人都有很多标签:
在User 类中添加:
public Set<Tag> getTags() {
return tags;
}
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
private Set<Tag> tags;
同时 添加 Tag类:
package com.rhythmk.model;
public class Tag {
public Integer getTagId() {
return tagId;
}
public void setTagId(Integer tagId) {
this.tagId = tagId;
}
public String getTagTitle() {
return tagTitle;
}
public void setTagTitle(String tagTitle) {
this.tagTitle = tagTitle;
}
public Integer getUserID() {
return userID;
}
@Override
public String toString() {
return "Tag [tagId=" + tagId + ", tagTitle=" + tagTitle + ", userID="
+ userID + "]";
}
public void setUserID(Integer userID) {
this.userID = userID;
}
private Integer tagId;
private String tagTitle;
private Integer userID;
}
添加User对应XML配置:
<set name="tags">
<key column="userID"></key>
<!-- 此处需要配置完成的类别-->
<one-to-many class="com.rhythmk.model.Tag" />
</set>
注意:此处 one-to-many 对应的 class 需要填写类的全路径名称
2.2 验证:
@Test
public void test01_add() {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Tag t1 = new Tag();
t1.setTagTitle("tag1"); Tag t2 = new Tag();
t2.setTagTitle("tag2"); Set<Tag> tags = new HashSet<Tag>();
tags.add(t1);
tags.add(t2); User entity = new User();
entity.setUserName("张飞2222");
entity.setCreateTime(new Date()); entity.setTags(tags);
session.save(t1);
session.save(t2);
session.save(entity); session.getTransaction().commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null)
session.close();
}
}
输出:
Hibernate: insert into t_tag (tagTitle) values (?)
Hibernate: insert into t_tag (tagTitle) values (?)
Hibernate: insert into t_user (userName, createTime) values (?, ?)
Hibernate: update t_tag set userID=? where tagId=?
Hibernate: update t_tag set userID=? where tagId=?
@Test
public void test02_get() {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction(); System.err.println("------01 -----------");
User entity = (User) session.get(User.class, 6);
System.err.println("------02 -----------");
for (Tag t : entity.getTags()) {
System.out.println(t);
} session.getTransaction().commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null)
session.close();
}
}
输出:
------01 -----------
Hibernate: select user0_.userID as userID1_3_0_, user0_.userName as userName2_3_0_, user0_.createTime as createTi3_3_0_ from t_user user0_ where user0_.userID=?
------02 -----------
Hibernate: select tags0_.userID as userID3_3_0_, tags0_.tagId as tagId1_2_0_, tags0_.tagId as tagId1_2_1_, tags0_.tagTitle as tagTitle2_2_1_ from t_tag tags0_ where tags0_.userID=?
Tag [tagId=2, tagTitle=tag1, userID=null]
Tag [tagId=3, tagTitle=tag2, userID=null]
>>> OneToMany 双相关联
背景:一个标签下有多少人
调整原标签代码:
<set name="users">
<key column="tagId"></key>
<!-- 此处需已在hibernate-mapping 上配置了 类包名-->
<one-to-many class="User" />
</set>
one-to-many class仅填写类名 现将包名调整到 hibernate-mapping属性上 如:
<hibernate-mapping package="com.rhythmk.model">
调整 Tag.java,添加:
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
private Set<User> users;
测试:
@Test
public void test01_add() {
Session session = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Tag t1 = new Tag();
t1.setTagTitle("tag1"); Tag t2 = new Tag();
t2.setTagTitle("tag2"); Set<Tag> tags = new HashSet<Tag>();
tags.add(t1);
tags.add(t2); User u1 = new User();
u1.setUserName("张飞2222");
u1.setCreateTime(new Date());
u1.setTags(tags); User u2 = new User();
u2.setUserName("张飞2333332");
u2.setCreateTime(new Date());
u2.setTags(tags); Set<User> users = new HashSet<User>();
users.add(u1);
users.add(u2); t1.setUsers(users); t2.setUsers(users); session.save(t1);
session.save(t2);
session.save(u1);
session.save(u2);
session.getTransaction().commit(); } catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null)
session.close();
}
}
输出:
Hibernate: insert into t_tag (tagTitle) values (?)
Hibernate: insert into t_tag (tagTitle) values (?)
Hibernate: insert into t_user (userName, createTime) values (?, ?)
Hibernate: insert into t_user (userName, createTime) values (?, ?)
Hibernate: update t_user set tagId=? where userID=?
Hibernate: update t_user set tagId=? where userID=?
Hibernate: update t_user set tagId=? where userID=?
Hibernate: update t_user set tagId=? where userID=?
Hibernate: update t_tag set userID=? where tagId=?
Hibernate: update t_tag set userID=? where tagId=?
Hibernate: update t_tag set userID=? where tagId=?
Hibernate: update t_tag set userID=? where tagId=?
注意:此处因为在提交事务过程中 Tag 以及User都相互影响变化,故出现12条SQL。
在实际项目中 我们并非需要 One 跟 Many都同时去维护数据,故引入 inverse,当inverse="true" 则不去维护对应关系,现修改User.hbm.xml 如下:
<set name="tags" lazy="extra" inverse="true">
<key column="userID"></key>
<!-- 此处需要配置完成的类别-->
<one-to-many class="com.rhythmk.model.Tag" />
</set>
执行测试输出:
Hibernate: insert into t_tag (tagTitle) values (?)
Hibernate: insert into t_tag (tagTitle) values (?)
Hibernate: insert into t_user (userName, createTime) values (?, ?)
Hibernate: insert into t_user (userName, createTime) values (?, ?)
Hibernate: update t_user set tagId=? where userID=?
Hibernate: update t_user set tagId=? where userID=?
Hibernate: update t_user set tagId=? where userID=?
Hibernate: update t_user set tagId=? where userID=?
代码下载地址:
http://pan.baidu.com/s/1gdFt7ur
Rhythmk 学习 Hibernate 05 - Hibernate 表间关系 [ManyToOne,OneToMany]的更多相关文章
- Rhythmk 学习 Hibernate 06 - Hibernate 表间关系 [One To One]
1.One To One 单相 背景: 古代一个老婆 只能关联一个老公 husband.java package com.rhythmk.model; public class husband { ...
- Hibernate第三天——表间关系与级联操作
第三天,我们来使用Hibernate进行表之间一对多 多对多关系的操作: 这里我们先利用两个例子进行表关系的回顾: 一对多(重点): 例如分类和商品的关系,一个分类多个商品,一个商品属于一个分类 CR ...
- EF简易教程,从建表到表间关系
唐大兵博客 唐大兵的博客里记录了EF Code First从建表到表之间关系的详细内容. 汪杰的博客(EF里一对一.一对多.多对多关系的配置和级联删除) 汪杰的博客更简洁,但不够充实,读懂了唐大兵博客 ...
- HTML5学习总结-05 HTML5表单
一 HTML5 新的类型 HTML5 拥有多个新的表单输入类型.这些新特性提供了更好的输入控制和验证. email url number range Date pickers (date, month ...
- Node.js ORM框架Sequlize之表间关系
Sequelize模型之间存在关联关系,这些关系代表了数据库中对应表之间的主/外键关系.基于模型关系可以实现关联表之间的连接查询.更新.删除等操作.本文将通过一个示例,介绍模型的定义,创建模型关联关系 ...
- 自增特性,外键,级联更新与级联删除,表间关系,SELECT用法,GROUP BY
自增特性 自动增长的作用: 问题:为数据表设置主键约束后,每次插入记录时,如果插入的值已经存在,会插入失败. 如何解决:为主键生成自动增长的值. 自动增长的语法: 字段名 数据类型 AUTO_INCR ...
- MicroERP开发技术分享:vsFlexGrid、scriptControl实现工资表自定义列与表间关系计算
开发大型的MIS系统,肯定是离不开第三方控件的,同时也要根据项目需要自己写几个. MicroERP共用了以下几个控件: 第三方商业控件: vsFlexGrid:大名鼎鼎的表格控件,不用多说,配合vsP ...
- Django 的ORM 表间操作
Django之ORM表间操作 之前完成了简单的数据库数据增加操作.这次学习更多的表间操作. 单表操作 增加 方式一 b = Book(title="Python基础", pub ...
- sql语句之表间字段值复制遇到的一些问题--基于mysql
好久没来园子了,转眼2017已经到3月份了,前段时间一直忙没时间写博客(其实是自己懒),感觉内心好惭愧.昨天临下班前,技术老大突然对我说要改下表结构,问我能不能实现将一个表的字段值复制到另外一个表的某 ...
随机推荐
- Learn Rails5.2 Routes。( 很少用到的参数:constraints和redirect)
Naming a Route get 'home/index', as: "different_name" 会得到prefix: different_name代替home_inde ...
- 数论练习(6)——hdu A/B(逆元gcd)
A/B Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 为了更好更方便地活着——爱上private
刚开始接触OOP的时候,打心底里我不喜欢private与protected.我声明一个public然后不直接用它,不就跟private一样吗?在某些场合下,我还能偷偷地用一下public变量,这不是更 ...
- CF 148D Bag of mice 概率dp 难度:0
D. Bag of mice time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...
- jQuery实现的手机发送验证码倒计时效果代码分享
这是一款基于jquery实现的手机发送验证码倒计时效果代码,可实现实时显示秒数倒计时的功能,还可实现对手机号码格式验证的功能,是一款常用的网站注册发送手机验证码特效代码. 效果描述:注册一个网站,当需 ...
- delphi7完全关闭一个窗体
如果一个工程中有若干个form,在程序运行中若要彻底关闭其中的一个窗体 除了点击右上角的小叉叉外,也可以在form的close事件中添加一句话 procedure TLockScreen.FormCl ...
- 『转』G Data InternetSecurity 2014 – 免费3个月
G Data来自德国的顶级杀毒软件,采用BitDefender+CloseGap双引擎,屡获AV-TEST防護率100%.不多介绍,目前2014中文版没有上市.活动地址:点此进入官方网站:点此进入申请 ...
- 『转』谷歌发布Windows版Chrome App Launcher
据国外媒体报道,谷歌发布了Windows版Chrome App Launcher,Windows用户现在因此能够使用谷歌的许多网络应用,如Chrome浏览器.Gmail.Google Drive和Ch ...
- 回首C语言关键字(~回首向来萧瑟处~)
开篇废话: 本文意在回顾 C 语言中的关键字,整理文件发现当时做的这些笔记还是蛮用心的,有临摹 前辈的足迹也有自己的理解和体会.时至今日2018已经跨过一半,对不起过去半年,今天 拿这篇关键字开篇,开 ...
- Word操作(基于word2013)【非编程类】
一.生成目录 1.word支持自动生成目录功能,生成地点为操作时光标的落点 2.生成方式:打开首选项,进入引用标签,如下图所示最左边即为目录选项. 一般有3个内置目录类型 a:手动目录,生成目录后只有 ...