本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用

内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。

本人互联网技术爱好者,互联网技术发烧友

微博:伊直都在0221

QQ:951226918

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1.双向 1-n

  1)域模型:从 Order 到 Customer 的多对一双向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中需定义存放 Order 对象的集合属性

    

  2)关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键

     

   

2.单向 n-1 关键点解释

  1)当 Session 从数据库中加载 Java 集合时, 创建的是 Hibernate 内置集合类的实例, 因此在持久化类中定义集合属性时必须把属性声明为 Java 接口类型

      > Hibernate 的内置集合类具有集合代理功能, 支持延迟检索策略

      > 事实上, Hibernate 的内置集合类封装了 JDK 中的集合类, 这使得 Hibernate 能够对缓存中的集合对象进行脏检查, 按照集合对象的状态来同步更新数据库。

  2)在定义集合属性时, 通常把它初始化为集合实现类的一个实例. 这样可以提高程序的健壮性, 避免应用程序访问取值为 null 的集合的方法抛出 NullPointerException

  3)Hibernate 使用 <set> 元素来映射 set 类型的属性        

  <!-- 在 1 端 -->
<!-- 映射 1对 n 的那个集合属性 -->
<!-- set:映射set类型的属性,
table:set 中的元素中的记录放在哪一个数据表中,该值 需要 n 端的表的名字一致
key:指定n 端 表中的外键列的名字
-->
<set name="orders" table="ORDERS">
<key column="CUSTOMER_ID"></key>
<!-- 指定映射类型 1 - n -->
<one-to-many class="Order"/>
</set>

3.代码

 <?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">
<hibernate-configuration>
<session-factory>
<!-- hibernate 连接数据库的基本信息 -->
<property name="connection.username">root</property>
<property name="connection.password">zhangzhen</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///hibernate</property> <!-- 配置hibernate 的节本信息 -->
<!-- hibernate 所使用的数据库方言 -->
<!--<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 执行操作时是否在控制台打印SQL -->
<property name="show_sql">true</property> <!-- 是否都SQL 进行格式化 -->
<property name="format_sql">true</property> <!-- 指定自动生成数据表的策略 -->
<property name="hbm2ddl.auto">update</property> <!-- 设置hibernate 的事务隔离级别 -->
<property name="connection.isolation">2</property> <!-- 配置c3p0 -->
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="c3p0.acquire_increment">2</property>
<property name="c3p0.idle_test_period">2000</property>
<property name="c3p0.timeout">2000</property>
<property name="c3p0.max_statements">10</property> <!-- 对于mysql 无效,对于oracle 有效 -->
<!-- 设定JDBC 的Statement 读取数据的时候每次从数据库中取出的记录的条数 -->
<property name="hibernate.jdbc.fetch_size">100</property> <!-- 设置数据库进行批量删除,批量更新和批量插入的时候的大小 -->
<property name="hibernate.jdbc.batch_size">30</property> <!-- 指定关联的 .hbm.xml 文件 -->
<!--
<mapping resource="hibernate/helloworld/News.hbm.xml"/>
<mapping resource="hibernate/helloworld/Worker.hbm.xml"/> <mapping resource="com/jason/hibernate/entities/n21/Customer.hbm.xml"/>
<mapping resource="com/jason/hibernate/entities/n21/Order.hbm.xml"/>
--> <mapping resource="com/jason/hibernate/entities/n21/both/Customer.hbm.xml"/>
<mapping resource="com/jason/hibernate/entities/n21/both/Order.hbm.xml"/> </session-factory> </hibernate-configuration>

hibernate.cfg.xml

Customer.hbm.xml

 <?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 2016-10-5 17:43:02 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.jason.hibernate.entities.n21.both"> <class name="Customer" table="CUSTOMERS"> <id name="customerId" type="java.lang.Integer">
<column name="CUSTOMER_ID" />
<generator class="native" />
</id> <property name="customerName" type="java.lang.String">
<column name="CUSTOMER_NAME" />
</property> <!-- 在 1 端 -->
<!-- 映射 1对 n 的那个集合属性 -->
<!-- set:映射set类型的属性,
table:set 中的元素中的记录放在哪一个数据表中,该值 需要 n 端的表的名字一致
key:指定n 端 表中的外键列的名字
-->
<set name="orders" table="ORDERS">
<key column="CUSTOMER_ID"></key>
<!-- 指定映射类型 1 - n -->
<one-to-many class="Order"/>
</set> </class> </hibernate-mapping>

Customer

 package com.jason.hibernate.entities.n21.both;

 import java.util.HashSet;
import java.util.Set; public class Customer { private Integer customerId;
private String customerName; /*
* 1.orders 初始化后,防止发生空指针异常
* 2.声明集合类型时,需使用接口类型,因为hibernate 在获取集合类型时,返回的是hibernate 内置的集合类型,而不是javaSE 的实现
*/
private Set<Order> orders = new HashSet<>();
public Set<Order> getOrders() {
return orders;
} public void setOrders(Set<Order> orders) {
this.orders = orders;
} 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;
} @Override
public String toString() {
return "Customer [customerId=" + customerId + ", customerName="
+ customerName + "]";
} }

Order.hbm.xml

 <?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 2016-10-5 17:43:02 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.jason.hibernate.entities.n21.both">
<class name="Order" table="ORDERS"> <id name="orderId" type="java.lang.Integer">
<column name="ORDER_ID" />
<generator class="native" />
</id> <property name="orderName" type="java.lang.String">
<column name="ORDER_NAME" />
</property> <!-- 映射 多对一 关联关系 -->
<!--
name: 'n'端 关联 '1'端的属性的名字
class: '1'端 属性对应的类名
colum: '1'端 在 'n'端 对应的数据表中的外键的名字
-->
<many-to-one name="customer" class="Customer">
<column name="CUSTOMER_ID" />
</many-to-one> </class> </hibernate-mapping>

Order

 package com.jason.hibernate.entities.n21.both;

 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;
} @Override
public String toString() {
return "Order [orderId=" + orderId + ", orderName=" + orderName
+ ", customer=" + customer + "]";
} }

HibernateTest.java

 package com.jason.hibernate.entities.n21.both;

 import hibernate.helloworld.News;
import hibernate.helloworld.Pay;
import hibernate.helloworld.Worker; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException; import org.hibernate.Hibernate;
import org.hibernate.LazyInitializationException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.omg.CORBA.ORB; public class HibernateTest { private SessionFactory sessionFactory;
private Session session;
private Transaction transaction; @Test
public void test() { // 1. 创建一个SessionFatory 对象
SessionFactory sessionFactory = null; // 1) 创建Configuration 对象:对应hibernate 的基本配置信息 和 对象关系映射信息
Configuration configuration = new Configuration().configure(); // 2) 创建一个ServiceRegistry 对象:hibernate 4.x 新天添加的对象。
// hibernate 的任何配置 和 服务都需要在该对象中注册后才有效
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry(); // sessionFactory = configuration.buildSessionFactory();
sessionFactory = configuration.buildSessionFactory(serviceRegistry); // 2. 创建一个session 对象
Session session = sessionFactory.openSession(); // 3. 开启事物
Transaction transaction = session.beginTransaction(); // 4.执行保存操作
News news = new News("java", "jason", new Date(
new java.util.Date().getTime()));
session.save(news); // 5.提交事物
transaction.commit();
// 6.关闭session
session.close();
// 7.关闭SessionFactory 对象
sessionFactory.close();
} // 创建上述三个对象
@Before
public void init() {
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction();
} // 关闭上述三个对象
@After
public void destroy() {
transaction.commit();
session.close();
sessionFactory.close();
} @Test
public void testDelete() {
// 在不设定级联关系的情况下,且 1 端的对象 有 n端的对象在引用,不能直接删除1 端的对象
Customer customer = (Customer) session.get(Customer.class, 1);
session.delete(customer);
} @Test
public void testUpdate2(){
Customer customer = (Customer) session.get(Customer.class, 1);
customer.getOrders().iterator().next().setOrderName("BBBB");
}
@Test
public void testUpdate() {
Order order = (Order) session.get(Order.class, 1);
order.getCustomer().setCustomerName("tom2"); } @Test
public void testOne2ManyGet() { //1.对n 的一端的集合使用延迟加载
Customer customer = (Customer) session.get(Customer.class, 1);
System.out.println(customer.getCustomerName()); //2.返回n端的集合是hibernate 的内置集合类型。该类型具有延迟加载和存放代理对象的功能
System.out.println(customer.getOrders().getClass()); //3.可能抛出 LazyInitializationException 异常 //4.再需要使用集合中元素的时候进行初始化 } @Test
public void testManyToOneGet() {
// 1.若查询n 的一端的对象,则默认情况下,只查询了n 的一端的对象,而没有查询关联的1 端的对象
// 延迟加载
Order order = (Order) session.get(Order.class, 1);
System.out.println(order); // 2.在需要使用到关联的对象,才发送对应的sql 语句
Customer customer = order.getCustomer();
System.out.println(customer); // 3.获取order对象,默认情况,其关联的Customer 对象是一个代理对象
} @Test
public void testManyToOneSave() {
Customer customer = new Customer();
customer.setCustomerName("AA"); Order order1 = new Order();
order1.setOrderName("order-1"); Order order2 = new Order();
order2.setOrderName("order-2"); // 设定关联关系
order1.setCustomer(customer);
order2.setCustomer(customer); customer.getOrders().add(order1);
customer.getOrders().add(order2); // 执行svae操作:先插入 Customer,再插入Order,3条insert,2条update
// 因为1端 和 n端 都维护关联关系,所以多出四条
// 可以在1 端的set节点,指定inverse=true ,来使1端放弃维护关联关系
// 建议先插入1 的一端,后插入 n端
//
session.save(customer);
session.save(order1);
session.save(order2); // 先插入Order,再插入Customer,3条insert,4条update
// session.save(order1);
// session.save(order2);
//
// session.save(customer); } }

关于set标签

  1) <set> 元素来映射持久化类的 set 类型的属性 name: 设定待映射的持久化类的属性的

  2)<key> 元素设定与所关联的持久化类对应的表的外键 column: 指定关联表的外键名

  3)<one-to-many> 元素设定集合属性中所关联的持久化类 class: 指定关联的持久化类的类名

  4)inverse 属性

    ① 在hibernate中通过对 inverse 属性的来决定是由双向关联的哪一方来维护表和表之间的关系. inverse = false 的为主动方,inverse = true 的为被动方, 由主动方负责维护关联关系

        ② 在没有设置 inverse=true 的情况下,父子两边都维护父子 关系

    ③ 在 1-n 关系中,将 n 方设为主控方将有助于性能改善(如果要国家元首记住全国人民的名字,不是太可能,但要让全国人民知道国家元首,就容易的多)

    ④ 在 1-N 关系中,若将 1 方设为主控方

      >会额外多出 update 语句。

      >插入数据时无法同时插入外键列,因而无法为外键列添加非空约束

  5)cascade 属性(了解)

    ① 在对象 – 关系映射文件中, 用于映射持久化类之间关联关系的元素, <set>, <many-to-one> 和 <one-to-one> 都有一个 cascade 属性, 它用于指定如何操纵与当前对象关联的其他对象.

  6)order-by 属性  

    ①  <set> 元素有一个 order-by 属性, 如果设置了该属性, 当 Hibernate 通过 select 语句到数据库中检索集合对象时, 利用 order by 子句进行排序。设置的是表的字段名,而不是持久化类的属性名

    ②  order-by 属性中还可以加入 SQL 函数

  

说明:
  1.在 n 端的 .hbm.xml 中映射关联关系
 <!-- 映射 多对一 关联关系 -->
<!--
name: 'n'端 关联 '1'端的属性的名字
class: '1'端 属性对应的类名
colum: '1'端 在 'n'端 对应的数据表中的外键的名字
-->
<many-to-one name="customer" class="Customer">
<column name="CUSTOMER_ID" />
</many-to-one>

  

[原创]java WEB学习笔记83:Hibernate学习之路---双向 1-n介绍,关键点解释,代码实现,set属性介绍(inverse,cascade ,order-by )的更多相关文章

  1. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁

    guava 学习笔记 使用瓜娃(guava)的选择和预判断使代码变得简洁 1,本文翻译自 http://eclipsesource.com/blogs/2012/06/06/cleaner-code- ...

  5. 学习笔记:CentOS7学习之二十:shell脚本的基础

    目录 学习笔记:CentOS7学习之二十:shell脚本的基础 20.1 shell 基本语法 20.1.1 什么是shell? 20.1.2 编程语言分类 20.1.3 什么是shell脚本 20. ...

  6. 学习笔记:CentOS7学习之十九:Linux网络管理技术

    目录 学习笔记:CentOS7学习之十九:Linux网络管理技术 本文用于记录学习体会.心得,兼做笔记使用,方便以后复习总结.内容基本完全参考学神教育教材,图片大多取材自学神教育资料,在此非常感谢MK ...

  7. 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用

    目录 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用 16.1 LVM的工作原理 16.1.1 LVM常用术语 16.1.2 LVM优点 16.2 创建LVM的基本步骤 16.2 ...

  8. 学习笔记:APP切图那点事儿–详细介绍android和ios平台

    学习笔记:APP切图那点事儿–详细介绍android和ios平台 转载自:http://www.woofeng.cn/articles/168.html   版权归原作者所有 作者:亚茹有李 原文地址 ...

  9. HTML+CSS学习笔记 (6) - 开始学习CSS

    HTML+CSS学习笔记 (6) - 开始学习CSS 认识CSS样式 CSS全称为"层叠样式表 (Cascading Style Sheets)",它主要是用于定义HTML内容在浏 ...

  10. 在Java Web程序中使用Hibernate

    在Java Web程序中使用Hibernate与普通Java程序一样.本文中将使用Servlet和JSP结合Hibernate实现数据库表的增删改查操作. Web程序中,hibernate.cfg.x ...

随机推荐

  1. JS初学者必备的几个经典案例(一)!!!

    一:选中复选框按钮可用    和     倒计时10秒后按钮可用 这是倒计时10秒后按钮可用 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 ...

  2. SQL 编辑

    局部变量: DECLARE @variable_name Datatype Variable_naem为局部变量的名称,Datatype为数据名称. 例如: DECLARE @name varchar ...

  3. FastMM、FastCode、FastMove的使用(图文并茂)

    FastMM是一个替换Embarcadero Delphi Win32应用程序的快速内存管理器,以及可以在多线程下使用,不容易产生内存碎片,并且无需使用外部DLL文件就可以支持共享内存. 使用方法:1 ...

  4. SIP学习(实例详解)

    本文摘自:http://blog.chinaunix.net/uid-20655530-id-1589483.html 学习 SIP 协议最快捷的方法是通过范例来学习, 找到了一个完整的呼叫流程,le ...

  5. 在zendstudio中添加注释

    /** * * * @access public * @param string $cat_id 分类查询字符串 * @return string */ 然后在function之前的一行打上/**然后 ...

  6. ios copy/strong/weak..使用总结

    总结 关于属性的这些选项的学习,做一下总结: 所有的属性,都尽可能使用nonatomic,以提高效率,除非真的有必要考虑线程安全. NSString:通常都使用copy,以得到新的内存分配,而不只是原 ...

  7. The Simplified Project Management Process

    One of the challenges of explaining project management to people who are unfamiliar with the approac ...

  8. 替换SearchBar 键盘上的 搜索 按钮

    for (UIView *searchBarSubview in [searchBar subviews]) {        if ([searchBarSubview conformsToProt ...

  9. JavaScript:复选框事件的处理

    复选框事件的处理 复选框本身也是多个组件的名字相同.所以在定义复选框的同事依然要使用document.all()取得全部的内容. 范例:操作复选框,要求是可以一个个去选择选项,也可以直接全选,全选按钮 ...

  10. Linux和Windows路由配置

    Linux和Windows路由配置 一.配置路由 1-       原则上一台主机只能有一条缺省路由.如果一台主机上有多个网段的话,请配置能够上网的那个网段的网关为缺省路由 Linux配置缺省路由: ...