映射一关联关

    在领域模型中,类与类之间最普遍的关系就是关联关系。

    在UML中,关联是有方向的。

以Cuntomer和Order为例:一个用户能发出多个订单,而一个订单只能属于一个客户,从Order到Customer的关联是多对一关联,而从Customer到Order是一对多关联

单向关联:

如果Order中有一个Customer的一个引用的话,是单向多对一。

(order是多 ,customer是一)

如果Customer中有一个Order集合的引用的话,是单向一对多。

双向关联:

如果Customer中有一个对Order集合的引用,而Order中有一个对Customer的引用的话,属于双向关联

 

单向n-1

单向n-1关联只需从n的一端可以访问1的一端

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

 

关系数据模型:ORDER表中的customer_id参照customer表的主键。

 

举例:

public class Customer {

    private Integer customerId;

    private String customerName;

 

public class Order {

    private Integer orderId;

    private String orderName;

   

    private Customer customer = new Customer();

 

 

<hibernate-mapping >

    <class name="com.clou.entity.n21.Customer" table="customers">

       <id name="customerId" type="integer">

           <column name="customer_id"></column>

           <generator class="native"></generator>

       </id>

       <property name="customerName" type="string">

           <column name="customer_name"></column>

       </property>

    </class>

</hibernate-mapping>

 

<hibernate-mapping package="com.clou.entity.n21">

    <class name="Order" table="orders">

       <id name="orderId" type="integer">

           <column name="order_id"></column>

           <generator class="native"></generator>

       </id>

       <property name="orderName" type="string">

           <column name="order_name"></column>

       </property>

       <!--

           映射多对一的关联关系 不能用property来描述

           因为这已经不再是一个简单的属性

           也不能用component 因为这也已经不再是一个简单的组成关系

           (组件:组成关系中,在实体类中的引用分成两种,一种是值类型,一种是实体类型

              值类型没有ID )

         -->

         <!-- 这个customer属性在Order表中对应一列 这列是customer_id(多表中的外键列) -->

         <!-- 映射多对一的关联关系,使用many-to-one 来映射多对一的关联关系

           name: 多这一段关联的一那一端的属性的名字

           class: 一那一端的属性赌赢的类名

           column : 一那一端在多的一端对应的数据表中的外键的列名

          -->

        <many-to-one name="customer" class="Customer"  column="customer_id">

        

        </many-to-one>

    </class>

</hibernate-mapping>

 

 

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

import org.hibernate.service.ServiceRegistryBuilder;

import org.junit.After;

import org.junit.Before;

import org.junit.Test;

 

public class HibernateTest01 {

   

    private SessionFactory sessionFactory;

    private Session session;

    private Transaction transaction;

   

    @Before

    public void init(){

       Configuration conf = new Configuration().configure();

       ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();

       sessionFactory = conf.buildSessionFactory(serviceRegistry);

       session = sessionFactory.openSession();

       transaction = session.beginTransaction();

    }

    @After

    public void destroy(){

       transaction.commit();

       session.close();

       sessionFactory.close();

    }

    @Test

    public void testMany2One(){

       Customer customer = new Customer();

       customer.setCustomerName("BB");

      

       Order order1 = new Order();

       order1.setOrderName("order-3");

      

       Order order2 = new Order();

       order2.setOrderName("order-4");

      

       //设定关联关系

       order1.setCustomer(customer);

       order2.setCustomer(customer);

      

       //执行save操作:先插入Customer,再插入Order , 3条INSERT语句

       //先插入1的一端, 再插入n 的一端 ,只有INSERT语句

//     session.save(customer);

//     session.save(order1);

//     session.save(order2);

      

       //先插入Order , 再插入Customer,3条INSERT ,两条UPDATE

       //先插入n 的一端,再插入1的一端,会多出UPDATE语句

       //因为在插入过的一端时,无法确定1的一端的外键值,所以只能等1的一端插入后,在额外发送UPDATE语句

       //推荐线插入1的一端,后插入n的一端

       session.save(order1);

       session.save(order2);

       session.save(customer);

    }

    @Test

    public void testMany2OneGet(){

       //1.若查询多的语段的一个对象,则默认情况下,只查询了多的一端的对象,

       //而没有查询关联的1的那端的对象!

       Order order = (Order) session.get(Order.class, 1);

       System.out.println(order.getOrderName());//如果只有这一句,则控制台打印一句查询语句

      

       System.out.println(order.getCustomer().getClass().getName());

      

       session.close();

      

       //在需要使用到关联的对象时,才发送对应的SQL语句。

       Customer customer = order.getCustomer();

       System.out.println(customer.getCustomerName());

      

       //3.在查询Customer对象时 ,由多的一端,导航到一的一端时 ,

       //若此时 session 已被关闭, 则默认情况下

       //会发生LazyInitializationException 异常

      

       //4.获取Order对象时 ,默认情况下,其关联的Customer对象时一个代理对象

       //我们用的load()方法获取的数据库对象其实也是一个代理对象

       //在我们用这个代理对象属性的时候,才会把代理对象进行初始化,如果我们在

       //用这个代理对象之前把session给关了,会发生晚加载异常

    }

    public void testDelete(){

       //在不设定级联关系的情况下,且1这一段的对象有n 的对象在引用,

       //不能直接删除 1这一端的对象

       Customer customer = (Customer) session.get(Customer.class, 1);

       session.delete(customer);

    }

    /**

     * 测试更新

     */

    @Test

    public void testUpdate(){

       Order order = (Order) session.get(Order.class, 1);

       order.getCustomer().setCustomerName("AAA");

    }

}