[原创]java WEB学习笔记82:Hibernate学习之路---映射 一对多关联关系,配置,CRUD方法测试及注意点
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用
内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。
本人互联网技术爱好者,互联网技术发烧友
微博:伊直都在0221
QQ:951226918
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.一对多关联关系
1)在领域模型中, 类与类之间最普遍的关系就是关联关系.
2)在 UML 中, 关联是有方向的:以 Customer 和 Order 为例: 一个用户能发出多个订单, 而一个订单只能属于一个客户. 从 Order 到 Customer 的关联是多对一关联; 而从 Customer 到 Order 是一对多关联
- 单向关联
- 双向关联
2.单向 n-1
1)单向 n-1 关联只需从 n 的一端可以访问 1 的一端
2)域模型: 从 Order 到 Customer 的多对一单向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中无需定义存放 Order 对象的集合属性
3)关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键
3.代码
1 package com.jason.hibernate.entities.n21; 2 3 public class Customer { 4 5 private Integer customerId; 6 private String customerName; 7 8 public Integer getCustomerId() { 9 return customerId; 10 } 11 12 public void setCustomerId(Integer customerId) { 13 this.customerId = customerId; 14 } 15 16 public String getCustomerName() { 17 return customerName; 18 } 19 20 public void setCustomerName(String customerName) { 21 this.customerName = customerName; 22 } 23 24 @Override 25 public String toString() { 26 return "Customer [customerId=" + customerId + ", customerName=" 27 + customerName + "]"; 28 } 29 30 31 }
1 package com.jason.hibernate.entities.n21; 2 3 public class Order { 4 5 private Integer orderId; 6 private String orderName; 7 8 private Customer customer; 9 10 public Integer getOrderId() { 11 return orderId; 12 } 13 14 public void setOrderId(Integer orderId) { 15 this.orderId = orderId; 16 } 17 18 public String getOrderName() { 19 return orderName; 20 } 21 22 public void setOrderName(String orderName) { 23 this.orderName = orderName; 24 } 25 26 public Customer getCustomer() { 27 return customer; 28 } 29 30 public void setCustomer(Customer customer) { 31 this.customer = customer; 32 } 33 34 @Override 35 public String toString() { 36 return "Order [orderId=" + orderId + ", orderName=" + orderName 37 + ", customer=" + customer + "]"; 38 } 39 40 41 }
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2016-10-5 17:43:02 by Hibernate Tools 3.4.0.CR1 --> 5 <hibernate-mapping> 6 7 <class name="com.jason.hibernate.entities.n21.Customer" table="CUSTOMERS"> 8 9 <id name="customerId" type="java.lang.Integer"> 10 <column name="CUSTOMER_ID" /> 11 <generator class="native" /> 12 </id> 13 14 <property name="customerName" type="java.lang.String"> 15 <column name="CUSTOMER_NAME" /> 16 </property> 17 18 </class> 19 20 </hibernate-mapping>
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2016-10-5 17:43:02 by Hibernate Tools 3.4.0.CR1 --> 5 <hibernate-mapping package="com.jason.hibernate.entities.n21"> 6 <class name="Order" table="ORDERS"> 7 8 <id name="orderId" type="java.lang.Integer"> 9 <column name="ORDER_ID" /> 10 <generator class="native" /> 11 </id> 12 13 <property name="orderName" type="java.lang.String"> 14 <column name="ORDER_NAME" /> 15 </property> 16 17 <!-- 映射 多对一 关联关系 --> 18 19 <!-- 20 name: 'n'端 关联 '1'端的属性的名字 21 class: '1'端 属性对应的类名 22 colum: '1'端 在 'n'端 对应的数据表中的外键的名字 23 --> 24 <many-to-one name="customer" class="Customer"> 25 <column name="CUSTOMER_ID" /> 26 </many-to-one> 27 28 </class> 29 30 </hibernate-mapping>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <!-- hibernate 连接数据库的基本信息 --> 8 <property name="connection.username">root</property> 9 <property name="connection.password">zhangzhen</property> 10 <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 11 <property name="connection.url">jdbc:mysql:///hibernate</property> 12 13 14 <!-- 配置hibernate 的节本信息 --> 15 <!-- hibernate 所使用的数据库方言 --> 16 <!--<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>--> 17 <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 18 <!-- 执行操作时是否在控制台打印SQL --> 19 <property name="show_sql">true</property> 20 21 <!-- 是否都SQL 进行格式化 --> 22 <property name="format_sql">true</property> 23 24 25 <!-- 指定自动生成数据表的策略 --> 26 <property name="hbm2ddl.auto">update</property> 27 28 <!-- 设置hibernate 的事务隔离级别 --> 29 <property name="connection.isolation">2</property> 30 31 32 <!-- 配置c3p0 --> 33 <property name="hibernate.c3p0.max_size">10</property> 34 <property name="hibernate.c3p0.min_size">5</property> 35 <property name="c3p0.acquire_increment">2</property> 36 <property name="c3p0.idle_test_period">2000</property> 37 <property name="c3p0.timeout">2000</property> 38 <property name="c3p0.max_statements">10</property> 39 40 41 <mapping resource="com/jason/hibernate/entities/n21/Customer.hbm.xml"/> 42 <mapping resource="com/jason/hibernate/entities/n21/Order.hbm.xml"/> 43 44 45 46 47 </session-factory> 48 49 </hibernate-configuration>
1 package com.jason.hibernate.entities.n21; 2 3 import hibernate.helloworld.News; 4 import hibernate.helloworld.Pay; 5 import hibernate.helloworld.Worker; 6 7 import java.io.FileInputStream; 8 import java.io.FileNotFoundException; 9 import java.io.InputStream; 10 import java.sql.Blob; 11 import java.sql.Connection; 12 import java.sql.Date; 13 import java.sql.SQLException; 14 15 import org.hibernate.Hibernate; 16 import org.hibernate.Session; 17 import org.hibernate.SessionFactory; 18 import org.hibernate.Transaction; 19 import org.hibernate.cfg.Configuration; 20 import org.hibernate.jdbc.Work; 21 import org.hibernate.service.ServiceRegistry; 22 import org.hibernate.service.ServiceRegistryBuilder; 23 import org.junit.After; 24 import org.junit.Before; 25 import org.junit.Test; 26 import org.omg.CORBA.ORB; 27 28 public class HibernateTest { 29 30 private SessionFactory sessionFactory; 31 private Session session; 32 private Transaction transaction; 33 @Test 34 public void test() { 35 36 // 1. 创建一个SessionFatory 对象 37 SessionFactory sessionFactory = null; 38 39 // 1) 创建Configuration 对象:对应hibernate 的基本配置信息 和 对象关系映射信息 40 Configuration configuration = new Configuration().configure(); 41 42 // 2) 创建一个ServiceRegistry 对象:hibernate 4.x 新天添加的对象。 43 // hibernate 的任何配置 和 服务都需要在该对象中注册后才有效 44 ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() 45 .applySettings(configuration.getProperties()) 46 .buildServiceRegistry(); 47 48 // sessionFactory = configuration.buildSessionFactory(); 49 sessionFactory = configuration.buildSessionFactory(serviceRegistry); 50 51 // 2. 创建一个session 对象 52 Session session = sessionFactory.openSession(); 53 54 // 3. 开启事物 55 Transaction transaction = session.beginTransaction(); 56 57 // 4.执行保存操作 58 News news = new News("java", "jason", new Date( 59 new java.util.Date().getTime())); 60 session.save(news); 61 62 // 5.提交事物 63 transaction.commit(); 64 // 6.关闭session 65 session.close(); 66 // 7.关闭SessionFactory 对象 67 sessionFactory.close(); 68 } 69 70 // 创建上述三个对象 71 @Before 72 public void init() { 73 Configuration configuration = new Configuration().configure(); 74 ServiceRegistry serviceRegistry = new ServiceRegistryBuilder() 75 .applySettings(configuration.getProperties()) 76 .buildServiceRegistry(); 77 78 sessionFactory = configuration.buildSessionFactory(serviceRegistry); 79 80 session = sessionFactory.openSession(); 81 82 transaction = session.beginTransaction(); 83 } 84 85 // 关闭上述三个对象 86 @After 87 public void destroy() { 88 transaction.commit(); 89 session.close(); 90 sessionFactory.close(); 91 } 92 93 94 @Test 95 public void testDelete(){ 96 //在不设定级联关系的情况下,且 1 端的对象 有 n端的对象在引用,不能直接删除1 端的对象 97 Customer customer = (Customer) session.get(Customer.class, 1); 98 session.delete(customer); 99 } 100 101 @Test 102 public void testUpdate(){ 103 Order order = (Order) session.get(Order.class, 1); 104 order.getCustomer().setCustomerName("tom2"); 105 106 } 107 @Test 108 public void testManyToOneGet(){ 109 //1.若查询n 的一端的对象,则默认情况下,只查询了n 的一端的对象,而没有查询关联的1 端的对象 110 //延迟加载 111 Order order = (Order) session.get(Order.class, 1); 112 System.out.println(order); 113 114 //2.在需要使用到关联的对象,才发送对应的sql 语句 115 Customer customer = order.getCustomer(); 116 System.out.println(customer); 117 118 119 //3.获取order对象,默认情况,其关联的Customer 对象是一个代理对象 120 } 121 122 123 @Test 124 public void testManyToOneSave(){ 125 Customer customer = new Customer(); 126 customer.setCustomerName("tom"); 127 128 Order order1 = new Order(); 129 order1.setOrderName("order-3"); 130 131 Order order2 = new Order(); 132 order2.setOrderName("order-4"); 133 134 //设定关联关系 135 order1.setCustomer(customer); 136 order2.setCustomer(customer); 137 138 //执行save 操作:先插入 customer,再插入Order, 3条insert语句 139 //先出入1的一端,在插入 n 的一端,只有 insert 语句 140 // session.save(customer); 141 // 142 // session.save(order1); 143 // session.save(order2); 144 145 146 //先出入 order ,在插入 customer 147 //3 条insert,2条update 148 //先插入n 的一端,再插入1的一端,会多出update 语句 149 //因为在插入n 的一端,无法确定1 的一端的外键,所以只能等1 的一端出入后,再额外的发送update 语句 150 151 session.save(order1); 152 session.save(order2); 153 session.save(customer); 154 155 156 157 158 } 159 160 161 162 163 164 }
说明:
1.在 n 端的 .hbm.xml 中映射关联关系
1 <!-- 映射 多对一 关联关系 -->
2 <!--
3 name: 'n'端 关联 '1'端的属性的名字
4 class: '1'端 属性对应的类名
5 colum: '1'端 在 'n'端 对应的数据表中的外键的名字
6 -->
7 <many-to-one name="customer" class="Customer">
8 <column name="CUSTOMER_ID" />
9 </many-to-one>
2.方法注意点:
1 @Test 2 public void testManyToOneGet(){ 3 //1.若查询n 的一端的对象,则默认情况下,只查询了n 的一端的对象,而没有查询关联的1 端的对象 4 //延迟加载 5 Order order = (Order) session.get(Order.class, 1); 6 System.out.println(order); 7 8 //2.在需要使用到关联的对象,才发送对应的sql 语句 9 Customer customer = order.getCustomer(); 10 System.out.println(customer); 11 12 13 //3.获取order对象,默认情况,其关联的Customer 对象是一个代理对象 14 }
1 @Test 2 public void testManyToOneSave(){ 3 Customer customer = new Customer(); 4 customer.setCustomerName("tom"); 5 6 Order order1 = new Order(); 7 order1.setOrderName("order-3"); 8 9 Order order2 = new Order(); 10 order2.setOrderName("order-4"); 11 12 //设定关联关系 13 order1.setCustomer(customer); 14 order2.setCustomer(customer); 15 16 //执行save 操作:先插入 customer,再插入Order, 3条insert语句 17 //先出入1的一端,在插入 n 的一端,只有 insert 语句 18 // session.save(customer); 19 // 20 // session.save(order1); 21 // session.save(order2); 22 23 24 //先出入 order ,在插入 customer 25 //3 条insert,2条update 26 //先插入n 的一端,再插入1的一端,会多出update 语句 27 //因为在插入n 的一端,无法确定1 的一端的外键,所以只能等1 的一端出入后,再额外的发送update 语句 28 29 session.save(order1); 30 session.save(order2); 31 session.save(customer); 32 33 }