hibernate关系映射之单向多对一和双向一对多


建立域模型和关系数据模型有着不同的出发点:
—域模型: 由程序代码组成, 通过细化持久化类的的粒度可提高代码的可重用性, 简化编程

—在没有数据冗余的情况下, 应该尽可能减少表的数目, 简化表之间的参照关系, 以便提高数据的访问速度

Hibernate 把持久化类的属性分为两种:
 值(value)类型(pay): 没有 OID, 不能被单独持久化, 生命周期依赖于所属的持久化类的对象的生命周期。
 实体(entity)类型(worker) 有 OID, 可以被单独持久化, 有独立的生命周期显然无法直接用 property 映射 pay 属性。
 Hibernate 使用 <component> 元素来映射组成关系, 该元素表名 pay 属性是 Worker 类一个组成部分, 在 Hibernate 中称之为组件。
  <!-- 映射组成关系 -->
        <component name="pay" class="Pay">
        <parent name="worker"/>
        <!-- 指定组成关系的组件的属性 -->
        <property name="monthlyPay" column="MONTHLY_PAY"></property>
        <property name="yearPay" column="YEAR_PAY"></property>
        <property name="vocationWithPay" column="VOCATION_WITH_PAY"></property>
        </component>

双向多对一关系——在元映射中添加如下属性



并且在实体类中互相添加相关属性元素
如:n端添加private Customer customer;当然也得添加必要的setter或getter方法。
      1端添加 /*
* 1. 声明集合类型时, 需使用 Java.util.Set接口类型, 因为 hibernate 在获取
* 集合类型时, 返回的是 Hibernate 内置的集合类型, 而不是 JavaSE 一个标准的
* 集合实现. 
* 2. 需要把集合进行初始化,使用的是具体的实现类, 可以防止发生空指针异常
*/
private Java.util.Set<Order> orders = new HashSet<>();
<!-- 映射 1 对多的那个集合属性 -->
        <!-- set: 映射 set 类型的属性, table: set 中的元素对应的记录放在哪一个数据表中. 该值需要和多对一的多的那个表的名字一致 -->
        <!-- inverse: 指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系 -->
        <!-- cascade 设定级联操作. 开发时不建议设定该属性. 建议使用手工的方式来处理 -->
        <!-- order-by 在查询时对集合中的元素进行排序, order-by 中使用的是表的字段名, 而不是持久化类的属性名  -->
        <set name="orders" table="ORDERS" inverse="true" order-by="ORDER_NAME DESC">cascade=“delete”或save-update或all或all-delete-orphan或delete-orphan
        <!-- 执行多的表中的外键列的名字 -->
        <key column="CUSTOMER_ID"></key>
        <!-- 指定映射类型 -->
        <one-to-many class="Order"/>
        </set>
@Test
public void testDelete(){
//在不设定级联关系的情况下, 且 1 这一端的对象有 n 的对象在引用, 不能直接删除 1 这一端的对象
//Customer customer = (Customer) session.get(Customer.class, 1);
//session.delete(customer); 
}

@Test
public void testUpdat2(){
Customer customer = (Customer) session.get(Customer.class, 1);
customer.getOrders().iterator().next().setOrderName("GrG"); 
}

@Test
public void testUpdate(){
Order order = (Order) session.get(Order.class, 1);
order.getCustomer().setCustomerName("FS");
}

@Test
public void testOne2ManyGet(){
//1. 对 n 的一端的集合使用延迟加载
Customer customer = (Customer) session.get(Customer.class, 1);
System.out.println(customer.getCustomerName()); 
//2. 返回的多的一端的集合时 Hibernate 内置的集合类型. 
//该类型具有延迟加载和存放代理对象的功能. lazy=“proxy”
System.out.println(customer.getOrders().getClass()); 

//session.close();
//3. 可能会抛出 LazyInitializationException 异常 ,在链接关闭的时候

System.out.println(customer.getOrders().size()); 

//4. 再需要使用集合中元素的时候进行初始化. 
}

单向一对多关系

需要在一的那一端加入多的属性比如order中加入Customer类的属性值。
<!-- 
映射多对一的关联关系。 使用 many-to-one 来映射多对一的关联关系 
name: 多这一端关联的一那一端的属性的名字
class: 一那一端的属性对应的类名
column: 一那一端在多的一端对应的数据表中的外键的名字
-->
<many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one>



@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();

//2. 在需要使用到关联的对象时, 才发送对应的 SQL 语句. 
Customer customer = order.getCustomer();
System.out.println(customer.getCustomerName()); 

//3. 在查询 Customer 对象时, 由多的一端导航到 1 的一端时, 
//若此时 session 已被关闭, 则默认情况下
//会发生 LazyInitializationException 异常

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

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值