hibernate学习(二)

                          hibernate 单向一对多映射

一.数据表设计

  数据库名:hibernate5

  数据表:  ①表名:CUSTOMERS            

        字段: CUSTOMER_ID

            CUSTOMER_NAME

                      ②表名:ORDERS

          字段:ORDER_ID

            ORDER_NUMBER

            CUSTOMER_ID(关联CUSTOMERS表的CUSTOMER_ID,构成单向一对多关系)

二.建立数据表对应的持久化类

  1.Customers.java

    

 1 package com.hjj.hibernate.entities.n21;
 2 public class Customer {
 3     private Integer customerId;
 4     private String customerName;
 5     
 6     
 7     public Customer(String customerName) {
 8         super();
 9         this.customerName = customerName;
10     }
11     
12     public Customer() {
13         super();
14     }
15 
16     public Integer getCustomerId() {
17         return customerId;
18     }
19     public void setCustomerId(Integer customerId) {
20         this.customerId = customerId;
21     }
22     public String getCustomerName() {
23         return customerName;
24     }
25     public void setCustomerName(String customerName) {
26         this.customerName = customerName;
27     }
28 
29     @Override
30     public String toString() {
31         return "Customer [customerId=" + customerId + ", customerName=" + customerName + "]";
32     }    
33 }

  2.Orders.java

    

 1 package com.hjj.hibernate.entities.n21;
 2 public class Order {
 3     private Integer orderId;
 4     private Customer customer;
 5     private  Integer  orderNumber;
 6 
 7     public Order() {
 8     
 9     }
10     public Order(Customer customer, Integer orderNumber) {
11         super();
12         this.customer = customer;
13         this.orderNumber = orderNumber;
14     }
15     public Integer getOrderId() {
16         return orderId;
17     }
18     public void setOrderId(Integer orderId) {
19         this.orderId = orderId;
20     }
21     public Customer getCustomer() {
22         return customer;
23     }
24     public void setCustomer(Customer customer) {
25         this.customer = customer;
26     }
27     public Integer getOrderNumber() {
28         return orderNumber;
29     }
30     public void setOrderNumber(Integer orderNumber) {
31         this.orderNumber = orderNumber;
32     }
33     @Override
34     public String toString() {
35         return "Order [orderId=" + orderId + ", customer=" + customer + ", orderNumber=" + orderNumber + "]";
36     }
37         
38 }

三.添加对象关系映射文件

  1.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-3-12 14:51:58 by Hibernate Tools 3.4.0.CR1 -->
 5 <hibernate-mapping>
 6     <class name="com.hjj.hibernate.entities.n21.Customer" table="CUSTOMERS">
 7         <id name="customerId" type="java.lang.Integer">
 8             <column name="CUSTOMER_ID" />
 9             <generator class="native" />
10         </id>
11         <property name="customerName" type="java.lang.String">
12             <column name="CUSTOMER_NAME" />
13         </property>
14     </class>
15 </hibernate-mapping>

  

  2. 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-3-12 14:51:58 by Hibernate Tools 3.4.0.CR1 -->
 5 <hibernate-mapping>
 6     <class name="com.hjj.hibernate.entities.n21.Order" table="ORDERS">
 7         <id name="orderId" type="java.lang.Integer">
 8             <column name="ORDER_ID" />
 9             <generator class="native" />
10         </id>
11       
12         <property name="orderNumber" type="java.lang.Integer">
13             <column name="ORDER_NUMBER" />
14         </property>
15         
16         <!--     name:属性名  所对应的 class:实体类                              -->
17         <!-- name: 多这一端关联的 一 那一端的属性的名字
18             class:一的那端的类名
19             column:一的那端的数据表字段名
20         
21          -->
22         <many-to-one name="customer" class="com.hjj.hibernate.entities.n21.Customer" >
23             <column name="CUSTOMER_ID" />
24         </many-to-one>
25     </class>
26 </hibernate-mapping>

四.配置hibernate.cfg.xml文件,并且把三中的两个关系映射文件关联到到此配置文件中.  

 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     <property name="connection.password">000000</property>
 8     <property name="connection.username">root</property>
 9     <property name="connection.url">jdbc:mysql:///hibernate5</property>
10     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
11    
12     <property name="dialect"> org.hibernate.dialect.MySQL5InnoDBDialect </property>
13     <property name="hbm2ddl.auto">update</property>
14     <property name="format_sql">true</property>
15     <property name="show_sql">true</property>
16   
17     <!--  指定关联的 .hbm.xml  -->
18     <mapping resource="com/hjj/hibernate/entities/n21/Customer.hbm.xml"/>
19     <mapping resource="com/hjj/hibernate/entities/n21/Order.hbm.xml"/>
20    
21    
22     </session-factory>
23 </hibernate-configuration>

 五.编写访问数据库的代码(使用单元测试类)。

  1.关于注解@Test @After @Before

  @Test:

    @Test注解的public void方法将会被当做测试用例,JUnit每次都会创建一个新的测试实例,然后调用@Test注解方法

  @Arter:

    使用@After注解一个public void方法会使该方法在@Test注解方法执行后被执行

  @Before

    使用@Before注解一个public void 方法会使该方法在@Test注解方法被执行前执行

  2. @After和@Before所做的事

    

 1 package com.hjj.hibernate.entities.n21;
 2 import org.hibernate.Session;
 3 import org.hibernate.SessionFactory;
 4 import org.hibernate.Transaction;
 5 import org.hibernate.cfg.Configuration;
 6 import org.junit.After;
 7 import org.junit.Before;
 8 import org.junit.Test;
 9 
10 public class HibernateTest {
11     private Session session ;
12     private SessionFactory sessionFactory ;
13     private Transaction transaction;
14     @Before
15     public void init(){
16         Configuration configuration = new Configuration().configure();
17         sessionFactory = configuration.buildSessionFactory();
18         session = sessionFactory.openSession();
19         transaction = session.beginTransaction();
20         
21     }
22     
23     @After
24     public void destory(){
25         transaction.commit();
26         session.close();
27         sessionFactory.close();
28     }
29 }

  3.@Test测试用例之save操作

    ①第一种save方法:先save customers关联对象(即先save一端),在save多端。

 1        @Test
 2         public void testSave(){
 3             
 4             Customer customer = new Customer();
 5             customer.setCustomerName("BB");
 6             
 7             Order order1 = new Order();
 8             order1.setOrderNumber(11111);
 9             
10             Order order2 = new Order();
11             order2.setOrderNumber(22222);
12             //设定关联关系
13             order1.setCustomer(customer);
14             order2.setCustomer(customer);
15     
16             session.save(customer);
17             session.save(order1);
18             session.save(order2);
19             
20         }           

    

  控制台发送三条insert语句

Hibernate: 
    insert 
    into
        CUSTOMERS
        (CUSTOMER_NAME) 
    values
        (?)
Hibernate: 
    insert 
    into
        ORDERS
        (ORDER_NUMBER, CUSTOMER_ID) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        ORDERS
        (ORDER_NUMBER, CUSTOMER_ID) 
    values
        (?, ?)

    ②。第二种save方法:先save order(即先save多端),在save一端。

  

    @Test
        public void testSave(){
            
            Customer customer = new Customer();
            customer.setCustomerName("BB");
            
            Order order1 = new Order();
            order1.setOrderNumber(11111);
            
            Order order2 = new Order();
            order2.setOrderNumber(22222);
            //设定关联关系
            order1.setCustomer(customer);
            order2.setCustomer(customer);
    
            //save操作:先插入多的一端 在插入一的一端
            
            session.save(order1);
            session.save(order2);
            session.save(customer);
                
        }

   控制台会发送三条insert语句,两条update语句.

Hibernate: 
    insert 
    into
        ORDERS
        (ORDER_NUMBER, CUSTOMER_ID) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        ORDERS
        (ORDER_NUMBER, CUSTOMER_ID) 
    values
        (?, ?)
Hibernate: 
    insert 
    into
        CUSTOMERS
        (CUSTOMER_NAME) 
    values
        (?)
Hibernate: 
    update
        ORDERS 
    set
        ORDER_NUMBER=?,
        CUSTOMER_ID=? 
    where
        ORDER_ID=?
Hibernate: 
    update
        ORDERS 
    set
        ORDER_NUMBER=?,
        CUSTOMER_ID=? 
    where
        ORDER_ID=?

    ③两种save方法的比较,可以明显的出第二种效率不如第一种.因此应该使用第一种save方式

    ④以上两种操作数据库表为下:

      CUSTOMERS表

      hibernate学习(二)

      

      ORDERS表

      hibernate学习(二)

  4.@Test测试用例之get操作

    ①正常编写代码

  @Test
    public void testGet(){
            Order order = (Order) session.get(Order.class, 1);
            System.out.println(order.getOrderNumber());    
    }

    控制台:

Hibernate:
select
  order0_.ORDER_ID as ORDER_ID1_2_0_,
  order0_.ORDER_NUMBER as ORDER_NU2_2_0_,
  order0_.CUSTOMER_ID as CUSTOMER3_2_0_
from
  ORDERS order0_
where
  order0_.ORDER_ID=?


order.getOrderNumber:11111

    可以看出来这里并没有去查询order关联的customer对象。

    ②.当使用到的关联对象  或者 关联对象 的属性的时候才会去查询

    

1   @Test
2     public void testGet(){
3             Order order = (Order) session.get(Order.class, 1);
4             System.out.println("order.getOrderNumber:"+order.getOrderNumber());
5             Customer customer = order.getCustomer();
6             System.out.println(customer);
7     
8     }

    

    控制台  

Hibernate: 
    select
        order0_.ORDER_ID as ORDER_ID1_2_0_,
        order0_.ORDER_NUMBER as ORDER_NU2_2_0_,
        order0_.CUSTOMER_ID as CUSTOMER3_2_0_ 
    from
        ORDERS order0_ 
    where
        order0_.ORDER_ID=?
order.getOrderNumber:11111
Hibernate: 
    select
        customer0_.CUSTOMER_ID as CUSTOMER1_0_0_,
        customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ 
    from
        CUSTOMERS customer0_ 
    where
        customer0_.CUSTOMER_ID=?
Customer [customerId=1, customerName=AAAAA]

    

      ③对于关联对象hibernate采用的是懒加载:对于 关联的对象 得到的是代理对象

1   @Test
2     public void testGet(){
3             Order order = (Order) session.get(Order.class, 1);
4             System.out.println("order.getOrderNumber:"+order.getOrderNumber());
5             System.out.println(order.getCustomer().getClass().getName());
6             
7     
8     }

   控制台:

Hibernate: 
    select
        order0_.ORDER_ID as ORDER_ID1_2_0_,
        order0_.ORDER_NUMBER as ORDER_NU2_2_0_,
        order0_.CUSTOMER_ID as CUSTOMER3_2_0_ 
    from
        ORDERS order0_ 
    where
        order0_.ORDER_ID=?
com.hjj.hibernate.entities.n21.Customer_$$_jvst392_0   //代理对象

  5.@Test测试用例之update操作

1 @Test
2     public void testUpdate(){
3             Order order = (Order) session.get(Order.class, 1);
4             order.getCustomer().setCustomerName("AAAAA");
5     
6     }

  控制台打印sql语句且数据库表中字段的记录也会相应的改变:

Hibernate: 
    select
        order0_.ORDER_ID as ORDER_ID1_2_0_,
        order0_.ORDER_NUMBER as ORDER_NU2_2_0_,
        order0_.CUSTOMER_ID as CUSTOMER3_2_0_ 
    from
        ORDERS order0_ 
    where
        order0_.ORDER_ID=?
    Hibernate: 
        select
            customer0_.CUSTOMER_ID as CUSTOMER1_0_0_,
            customer0_.CUSTOMER_NAME as CUSTOMER2_0_0_ 
        from
            CUSTOMERS customer0_ 
        where
            customer0_.CUSTOMER_ID=?
    Hibernate: 
        update
            CUSTOMERS 
        set
            CUSTOMER_NAME=? 
        where
            CUSTOMER_ID=?

  6..@Test测试用例之delete操作

  

1   @Test
2     public void testMany2OneDelete(){
3             Customer customer = session.get(Customer.class,1);
4             session.delete(customer);
5     
6     }

  这样是会抛出异常:org.hibernate.exception.ConstraintViolationException: could not execute statement

  因为有多端的对象对它还有引用。因此不能直接删除这个对象.