zoukankan      html  css  js  c++  java
  • [原创]java WEB学习笔记83:Hibernate学习之路---双向 1-n介绍,关键点解释,代码实现,set属性介绍(inverse,cascade ,order-by )

     

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

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

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

    微博:伊直都在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 端 -->
     2          <!-- 映射 1对 n 的那个集合属性 -->
     3          <!-- set:映射set类型的属性,
     4               table:set 中的元素中的记录放在哪一个数据表中,该值 需要 n 端的表的名字一致
     5               key:指定n 端 表中的外键列的名字
     6           -->
     7         <set name="orders" table="ORDERS">
     8             <key column="CUSTOMER_ID"></key>
     9             <!-- 指定映射类型  1 - n -->
    10             <one-to-many class="Order"/>
    11         </set>

    3.代码

     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         <!-- 对于mysql 无效,对于oracle 有效 -->
    42         <!-- 设定JDBC 的Statement 读取数据的时候每次从数据库中取出的记录的条数 -->
    43         <property name="hibernate.jdbc.fetch_size">100</property>
    44         
    45         <!-- 设置数据库进行批量删除,批量更新和批量插入的时候的大小 -->
    46         <property name="hibernate.jdbc.batch_size">30</property>
    47         
    48         <!-- 指定关联的 .hbm.xml 文件 -->
    49         <!-- 
    50             <mapping resource="hibernate/helloworld/News.hbm.xml"/>
    51             <mapping resource="hibernate/helloworld/Worker.hbm.xml"/>
    52         
    53             <mapping resource="com/jason/hibernate/entities/n21/Customer.hbm.xml"/>
    54             <mapping resource="com/jason/hibernate/entities/n21/Order.hbm.xml"/>
    55         -->
    56         
    57          <mapping resource="com/jason/hibernate/entities/n21/both/Customer.hbm.xml"/>       
    58          <mapping resource="com/jason/hibernate/entities/n21/both/Order.hbm.xml"/>       
    59         
    60         
    61         
    62         
    63     </session-factory>
    64     
    65 </hibernate-configuration>
    hibernate.cfg.xml

    Customer.hbm.xml

     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.both">
     6 
     7     <class name="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         
    19         
    20          <!-- 在 1 端 -->
    21          <!-- 映射 1对 n 的那个集合属性 -->
    22          <!-- set:映射set类型的属性,
    23               table:set 中的元素中的记录放在哪一个数据表中,该值 需要 n 端的表的名字一致
    24               key:指定n 端 表中的外键列的名字
    25           -->
    26         <set name="orders" table="ORDERS">
    27             <key column="CUSTOMER_ID"></key>
    28             <!-- 指定映射类型  1 - n -->
    29             <one-to-many class="Order"/>
    30         </set>
    31         
    32         
    33     </class>
    34     
    35 </hibernate-mapping>

    Customer

     1 package com.jason.hibernate.entities.n21.both;
     2 
     3 import java.util.HashSet;
     4 import java.util.Set;
     5 
     6 public class Customer {
     7 
     8     private Integer customerId;
     9     private String customerName;
    10 
    11     /*
    12      * 1.orders 初始化后,防止发生空指针异常
    13      * 2.声明集合类型时,需使用接口类型,因为hibernate 在获取集合类型时,返回的是hibernate 内置的集合类型,而不是javaSE 的实现
    14      */
    15     private Set<Order> orders = new HashSet<>();
    16     public Set<Order> getOrders() {
    17         return orders;
    18     }
    19 
    20     public void setOrders(Set<Order> orders) {
    21         this.orders = orders;
    22     }
    23 
    24     public Integer getCustomerId() {
    25         return customerId;
    26     }
    27 
    28     public void setCustomerId(Integer customerId) {
    29         this.customerId = customerId;
    30     }
    31 
    32     public String getCustomerName() {
    33         return customerName;
    34     }
    35 
    36     public void setCustomerName(String customerName) {
    37         this.customerName = customerName;
    38     }
    39 
    40     @Override
    41     public String toString() {
    42         return "Customer [customerId=" + customerId + ", customerName="
    43                 + customerName + "]";
    44     }
    45 
    46     
    47 }

    Order.hbm.xml

     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.both">
     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             name: 'n'端 关联 '1'端的属性的名字
    20             class: '1'端 属性对应的类名
    21             colum: '1'端  在 'n'端 对应的数据表中的外键的名字
    22          -->
    23         <many-to-one name="customer" class="Customer">
    24             <column name="CUSTOMER_ID" />
    25         </many-to-one>
    26         
    27        
    28         
    29     </class>
    30     
    31 </hibernate-mapping>

    Order

     1 package com.jason.hibernate.entities.n21.both;
     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 }

    HibernateTest.java

      1 package com.jason.hibernate.entities.n21.both;
      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.LazyInitializationException;
     17 import org.hibernate.Session;
     18 import org.hibernate.SessionFactory;
     19 import org.hibernate.Transaction;
     20 import org.hibernate.cfg.Configuration;
     21 import org.hibernate.jdbc.Work;
     22 import org.hibernate.service.ServiceRegistry;
     23 import org.hibernate.service.ServiceRegistryBuilder;
     24 import org.junit.After;
     25 import org.junit.Before;
     26 import org.junit.Test;
     27 import org.omg.CORBA.ORB;
     28 
     29 public class HibernateTest {
     30 
     31     private SessionFactory sessionFactory;
     32     private Session session;
     33     private Transaction transaction;
     34 
     35     @Test
     36     public void test() {
     37 
     38         // 1. 创建一个SessionFatory 对象
     39         SessionFactory sessionFactory = null;
     40 
     41         // 1) 创建Configuration 对象:对应hibernate 的基本配置信息 和 对象关系映射信息
     42         Configuration configuration = new Configuration().configure();
     43 
     44         // 2) 创建一个ServiceRegistry 对象:hibernate 4.x 新天添加的对象。
     45         // hibernate 的任何配置 和 服务都需要在该对象中注册后才有效
     46         ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
     47                 .applySettings(configuration.getProperties())
     48                 .buildServiceRegistry();
     49 
     50         // sessionFactory = configuration.buildSessionFactory();
     51         sessionFactory = configuration.buildSessionFactory(serviceRegistry);
     52 
     53         // 2. 创建一个session 对象
     54         Session session = sessionFactory.openSession();
     55 
     56         // 3. 开启事物
     57         Transaction transaction = session.beginTransaction();
     58 
     59         // 4.执行保存操作
     60         News news = new News("java", "jason", new Date(
     61                 new java.util.Date().getTime()));
     62         session.save(news);
     63 
     64         // 5.提交事物
     65         transaction.commit();
     66         // 6.关闭session
     67         session.close();
     68         // 7.关闭SessionFactory 对象
     69         sessionFactory.close();
     70     }
     71 
     72     // 创建上述三个对象
     73     @Before
     74     public void init() {
     75         Configuration configuration = new Configuration().configure();
     76         ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
     77                 .applySettings(configuration.getProperties())
     78                 .buildServiceRegistry();
     79 
     80         sessionFactory = configuration.buildSessionFactory(serviceRegistry);
     81 
     82         session = sessionFactory.openSession();
     83 
     84         transaction = session.beginTransaction();
     85     }
     86 
     87     // 关闭上述三个对象
     88     @After
     89     public void destroy() {
     90         transaction.commit();
     91         session.close();
     92         sessionFactory.close();
     93     }
     94 
     95     @Test
     96     public void testDelete() {
     97         // 在不设定级联关系的情况下,且 1 端的对象 有 n端的对象在引用,不能直接删除1 端的对象
     98         Customer customer = (Customer) session.get(Customer.class, 1);
     99         session.delete(customer);
    100     }
    101 
    102     
    103     @Test
    104     public void testUpdate2(){
    105         Customer customer = (Customer) session.get(Customer.class, 1);
    106         customer.getOrders().iterator().next().setOrderName("BBBB");
    107     }
    108     @Test
    109     public void testUpdate() {
    110         Order order = (Order) session.get(Order.class, 1);
    111         order.getCustomer().setCustomerName("tom2");
    112 
    113     }
    114 
    115     @Test
    116     public void testOne2ManyGet() {
    117         
    118         //1.对n 的一端的集合使用延迟加载
    119         Customer customer = (Customer) session.get(Customer.class, 1);
    120         System.out.println(customer.getCustomerName());
    121         
    122         //2.返回n端的集合是hibernate 的内置集合类型。该类型具有延迟加载和存放代理对象的功能
    123         System.out.println(customer.getOrders().getClass());
    124         
    125         //3.可能抛出     LazyInitializationException 异常
    126         
    127         //4.再需要使用集合中元素的时候进行初始化
    128     
    129         
    130         
    131     }
    132     
    133     
    134     @Test
    135     public void testManyToOneGet() {
    136         // 1.若查询n 的一端的对象,则默认情况下,只查询了n 的一端的对象,而没有查询关联的1 端的对象
    137         // 延迟加载
    138         Order order = (Order) session.get(Order.class, 1);
    139         System.out.println(order);
    140 
    141         // 2.在需要使用到关联的对象,才发送对应的sql 语句
    142         Customer customer = order.getCustomer();
    143         System.out.println(customer);
    144 
    145         // 3.获取order对象,默认情况,其关联的Customer 对象是一个代理对象
    146     }
    147 
    148     @Test
    149     public void testManyToOneSave() {
    150         Customer customer = new Customer();
    151         customer.setCustomerName("AA");
    152 
    153         Order order1 = new Order();
    154         order1.setOrderName("order-1");
    155 
    156         Order order2 = new Order();
    157         order2.setOrderName("order-2");
    158 
    159         // 设定关联关系
    160         order1.setCustomer(customer);
    161         order2.setCustomer(customer);
    162 
    163         customer.getOrders().add(order1);
    164         customer.getOrders().add(order2);
    165 
    166         // 执行svae操作:先插入 Customer,再插入Order,3条insert,2条update
    167         // 因为1端 和 n端 都维护关联关系,所以多出四条
    168         // 可以在1 端的set节点,指定inverse=true ,来使1端放弃维护关联关系
    169         // 建议先插入1 的一端,后插入 n端
    170         //
    171         session.save(customer);
    172         session.save(order1);
    173         session.save(order2);
    174 
    175         // 先插入Order,再插入Customer,3条insert,4条update
    176         // session.save(order1);
    177         // session.save(order2);
    178         //
    179         // session.save(customer);
    180 
    181     }
    182 
    183 }

    关于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 中映射关联关系
    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>








      
  • 相关阅读:
    洛谷—— P2234 [HNOI2002]营业额统计
    BZOJ——3555: [Ctsc2014]企鹅QQ
    CodeVs——T 4919 线段树练习4
    python(35)- 异常处理
    August 29th 2016 Week 36th Monday
    August 28th 2016 Week 36th Sunday
    August 27th 2016 Week 35th Saturday
    August 26th 2016 Week 35th Friday
    August 25th 2016 Week 35th Thursday
    August 24th 2016 Week 35th Wednesday
  • 原文地址:https://www.cnblogs.com/jasonHome/p/5932744.html
Copyright © 2011-2022 走看看