`
liumayulingyan
  • 浏览: 155385 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

Hibernate中inverse属性与cascade属性的使用方法

 
阅读更多
原文http://www.toceansoft.com/java/825.jhtml
Hibernate集 合映射中,经常会使用到"inverse"和"cascade"这两个属性。对于我这样,Hibernate接触不深和语文水平够烂的种种因素,发现这两 个属性实在是难以理解,无奈只好将这个两个属性解释工作交给了Google和Baidu,查看了许多牛人的解释,加上自己在Eclipse上的调试, 对"inverse"和"cascade"这两个属性有了一定的见解。
"inverse"属性探究
"inverse"-直 译过来就是"反转,使颠倒"的意思,书面化的解释为"是否将关系维护的权力交给对方"(这个解释真够蛋疼的-_-!!,就是理解不了)。 Hibernate中的"inverse"属性只有两个值"true"和"false"。"true"表示将关系维护的权力交给对方,"false"表示 不交出维护权力(默认值)。
例如有两张表,customer和orders,他们的关系是一对多,customer是一方,orders为多方。
1. drop table if exists customer;
2. drop table if exists orders;
3.
4. create table customer
5. (
6. id varchar(255) not null,
7. username varchar(255),
8. password varchar(255),
9. age integer,
10. register_time datetime,
11. primary key (id)
12. );
13.
14. create table orders
15. (
16. id varchar(255) not null,
17. orderNumber varchar(255),
18. balance integer,
19. customer_id varchar(255),
20. primary key (id)
21. );
两表对应的hbm文件,对应的POJO类:
1. /*customer表对应的POJO类*/
2. public class Customer
3. {
4. private String id;
5. private String username;
6. private String password;
7. private Timestamp registerTime;
8. private int age;
9. private Set<Order> orders = new HashSet<Order>();
10.
11. public Customer()
12. {
13.
14. }
15.
16. /*get and set method*/
17.
18. }
19.
20. /*orders表对应的POJO类*/
21. public class Order
22. {
23. private String id;
24. private String orderNumber;
25. private int balance;
26. private Customer customer;
27.
28. public Order()
29. {
30.
31. }
32.
33. /* get and set method*/
34. }
1. <!--Customer类的hbm文件-->
2. <hibernate-mapping>
3. <class name="com.suxiaolei.hibernate.pojos.Customer" table="customer">
4. <id name="id" type="string">
5. <column name="id"></column>
6. <generator class="uuid"></generator>
7. </id>
8.
9. <property name="username" column="username" type="string"></property>
10. <property name="password" column="password" type="string"></property>
11. <property name="age" column="age" type="integer"></property>
12. <property name="registerTime" column="register_time" type="timestamp"></property>
13.
14. <set name="orders" inverse="true" cascade="all">
15. <key column="customer_id" ></key>
16. <one-to-many class="com.suxiaolei.hibernate.pojos.Order"/>
17. </set>
18.
19. </class>
20. </hibernate-mapping>
21.
22. <!--Order类的hbm文件-->
23. <hibernate-mapping>
24. <class name="com.suxiaolei.hibernate.pojos.Order" table="orders">
25. <id name="id" type="string">
26. <column name="id"></column>
27. <generator class="uuid"></generator>
28. </id>
29.
30. <property name="orderNumber" column="orderNumber" type="string"></property>
31. <property name="balance" column="balance" type="integer"></property>
32.
33. <many-to-one name="customer" class="com.suxiaolei.hibernate.pojos.Customer">
34. <column name="customer_id"></column>
35. </many-to-one>
36. </class>
37. </hibernate-mapping>
下面写一些测试代码测试"inverse"属性的特性:
 
情况一:将"inverse"设置为true,让多方维护关系
1. try
2. {
3. tx = session.beginTransaction();
4.
5. /*
6. * 创建Customer对象,并设置其属性值
7. */
8. Customer customer = new Customer();
9. customer.setUsername("zhangsan");
10. customer.setPassword("123456");
11. customer.setAge(22);
12. customer.setRegisterTime(new Timestamp(new Date().getTime()));
13.
14. /*
15. * 创建Order对象order1,并设置其属性值
16. */
17. Order order1 = new Order();
18. order1.setOrderNumber("a1a2a3");
19. order1.setBalance(1000);
20. order1.setCustomer(customer);//将customer对象关联到order1对象上
21.
22. /*
23. * 创建Order对象order2,并设置其属性值
24. */
25. Order order2 = new Order();
26. order2.setOrderNumber("d3d2d1");
27. order2.setBalance(670);
28. order2.setCustomer(customer);///将customer对象关联到order2对象上
29.
30. customer.getOrders().add(order1);//将order1对象关联到customer对象上
31. customer.getOrders().add(order2);//将order2对象关联到customer对象上
32.
33. session.saveOrUpdate(customer);
34.
35. tx.commit();
36. }
37. catch (Exception e)
38. {
39. if(tx != null)
40. {
41. tx.rollback();
42. }
43.
44. e.printStackTrace();
45. }
46. finally
47. {
48. session.close();
49. }
数据库中的数据更新为:
customer表:
orders表:
现在将order1.setCustomer(customer);这段代码注释掉,再次运行程序:
customer表:
orders表:
可以到看到显著地差别了,第一次保 存"id"="402881e534ea7c750134ea7c76bc0001"的数据时,orders表中插入了两条数据,他们的 customer_id都为customer中对应记录的主键值,而第二次保存记 录"id"="402881e534ea81be0134ea81bfea0001"的数据时,由于先前将原来的代码段 order1.setCustomer(customer);注释掉了,此时order表中插入的数据中order1代表的那条记录没有 customer_id值。
从以上现象可以有助于理解"inverse"这个属性。首 先,"inverse"控制关系维护权力,那么什么是"关系"?,关系的具体体现是什么?在以上例子中,"关系"就是两个表之间的关系,通常为"一对 多","一对一","多对多"三种关系,而关系的具体体现为orders表中的 customer_id列,而"inverse"属性就是告诉Hibernate哪一方有权力管理和维护这一列。上面的例子将"inverse"设置为 true那么customer_id这一列由多方(order对象)维护。这说明了,只有order对象对关系的操作会反映到数据库中。(对象对关系的操 作就是对关联属性的操作,例如order对象对自身的"customer"属性操作,customer对象对自身的orders集合 (Set<Order>)操作)
例如,将id="402881e534ea7c750134ea7c76bc0001"的customer对象从数据库中取出,获取到该customer对象所关联的order对象集合,将该customer对象所关联的order对象删除。
1. Customer customer = (Customer)session.get(Customer.class,
"402881e534ea7c750134ea7c76bc0001");
2. Order order = (Order)session.get(Order.class, "402881e534ea7c750134ea7c76ce0002");
3.
4. System.out.println("customer association order count:"+customer.getOrders().size());
5. customer.getOrders().remove(order);
6. System.out.println("customer association order count:"+customer.getOrders().size());
7.
8. session.saveOrUpdate(customer);
//Console Output:
customer association order count:2
customer association order count:1
可以看到customer中关联的order对象集合确实有对象被删除了,若操作有效,表示该order对象与customer对象没有关系了,反映到数据库中应该将该order对象对应的customer_id设置为null。现在查看一下数据库数据:
看到了吧,刚刚那个操作就是个无用操作,不会反应到数据库中。我们修改一下程序代码:
1. Customer customer = (Customer)session.get(Customer.class,
"402881e534ea7c750134ea7c76bc0001");
2. Order order = (Order)session.get(Order.class, "402881e534ea7c750134ea7c76ce0002");
3.
4. order.setCustomer(null);
5.
6. session.saveOrUpdate(customer);
这次我们使用order对象来操作关系,将该order对象与customer对象脱离关系,若操作有效,则反映在数据库中应该是该order对象的customer_id字段的值变成null,现在查看一下数据库:
可以看到,此次操作成功的反映到了数据库中了。
情况二:将"inverse"属性设置为"false",双方都维护关系(因为没有一方交出权力,"inverse"的默认值为"false",而且"inverse"属性只能在set、list、map等几个标签中设置,像many-to-one这一类的标签都不能设置"inverse"这个属性值,它们只能取值"false")
这里会产生书中所说的性能问题(囧,这个也是理解了很久很久),这个不管怎么说你都可能理解不了,我就是这样的(-_-!!),所以我建议使用第三方的软件将Hibernate输出的SQL语句的绑定值显示出来(
可以参考这里)。之所以会产生性能为题,当你操作关系是会无故多产生一些update语句,比如你使用上面的例子保存一个customer对象,它关联了2个order对象,它不但会生成3条insert语句(用于插入数据),还会生成2条update语句(将关联的order对象的customer_id更新为自己的主键值),你想想要是一个customer对象包含几万了order对象(购物狂),那么每次保存它得要多生成几万条update语句,这个就是很严重的性能问题了。
为什么Hibernate会产生update语句呢?那是 Hibernate太主动,太热情,太负责的表现,它怕你出现错误,例如有几万个order对象需要关联到customer对象上,这就需要调用 order.setCustomer(customer);,几万个对象这不是人可以不放错的完成的。所以Hibernate怕你出错忘记调用这个方法, 所以他将会在order对象保存完毕后将所有关联对象的customer_id字段更新一遍,确保正确性,这样也就产生上面的性能问题。
将"inverse"设置为false后,你可以尝试设置order1.setCustomer(null),它依然会正确的将customer的主键值完美的插入到order的customer_id字段上,只是会多一条update语句。
"cascade"属性
"cascade"-直 译过来就是"级联、串联"的意思,书面化的解释为"该属性会使我们在操作主对象时,同时Hibernate帮助我们完成从属对象相应的操作(比如,有 Customer和Order这两张表,关系为一对多,只使用JDBC删除Customer表中的一行记录时,我们还需要手动的将Order表中与之关联 的记录全都删除,使用Hibernate的'cascade'属性后,当我们删除一条Customer记录时,Hibernate会帮助我们完成相应 Order表记录的删除工作,方便了我们的工作)"。
总 结
使用"inverse"这个属性时,要考虑清楚关系,不然你的系统就会有 大的性能问题(不过我可能想不清楚,现在还是一个普通大学生没什么实战经验-_-!!,要继续努力~_~),书本上和一些牛人建议,关系一般由"多方"维 护,当遇到"多对多"时怎么办,其实多对多久是两个"一对多",随意设置一方"inverse"为"true"就可以了,不要两方都设置或都不设置(囧, 我开始就是死板这样的设置)。而是用"cascade"属性时,主对象(一方)一般设置为"all",而多方不建议设置包含delete操作的选项,建议 设置多方为"save-update",这是因为你删除一方,多方已经没有存在的意义了,而删除多方不能代表一方没意义了(例如,消费者和订单)。最 后,"cascade"操作的是两张表的记录或两端的对象,而"inverse"操作的是两张表的关系或两个对象的关系。
分享到:
评论

相关推荐

    Hibernate中cascade与inverse属性详解

    Hibernate中cascade与inverse属性详解

    Hibernate中Inverse和Cascade的区别.html

    Hibernate中Inverse和Cascade的区别.html

    hibernate inverse和cascade的详细讲解

    与`inverse`不同,`cascade`属性可以应用于所有涉及到关联的元素,如`&lt;many-to-one&gt;`、`&lt;one-to-one&gt;`、`&lt;any&gt;`、`&lt;set&gt;`、`&lt;bag&gt;`、`&lt;idbag&gt;`、`&lt;list&gt;`和`&lt;array&gt;`。 - **Cascade 的作用** - **定义**:`cascade...

    hibernate集合映射inverse和cascade详解.txt

    在深入探讨Hibernate集合映射中的`inverse`与`cascade`属性之前,我们首先需要理解Hibernate框架的基本概念。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用程序提供了一种将对象模型与数据库...

    Hibernate中cascade和inverse应用

    在 Hibernate 框架中,`cascade` 和 `inverse` 是两个重要的概念,它们主要用于管理对象之间的持久化关系,特别是涉及到一对一(one-to-one)、一对多(one-to-many)和多对多(many-to-many)关系时。这两个属性都...

    inverse和cascade使用阐述

    至于博文链接,虽然没有提供具体内容,但可以推测博主可能详细讲解了在特定工具或框架中如何配置和使用“inverse”和“cascade”,并可能给出了一些示例和最佳实践。 在压缩包文件“inverse_cascade”中,可能包含...

    hibernate 级联(cascade和inverse)一对多

    下面将详细阐述这两个概念以及如何在实际应用中使用它们。 一、Hibernate级联(Cascade) 级联操作允许我们将对一个实体的更改自动应用到与之关联的其他实体。在一对多关系中,如果一个实体(父实体)与多个实体...

    关于cascade和inverse属性[文].pdf

    在软件网络技术领域,尤其是在使用Hibernate这种对象关系映射(ORM)框架时,理解和正确使用`cascade`和`inverse`属性至关重要。这两个属性主要用于管理对象之间的关联关系,特别是如何在数据库中维护这些关系。 ...

    JavaEE学习笔记之Hibernate表关系之一对多(inverse详解)

    2. **级联操作**:`inverse`属性常与`cascade`属性一起使用。`cascade`定义了关联实体的操作是否应级联到另一端。例如,`cascade="save-update"`意味着当父实体被保存或更新时,其关联的子实体也会随之保存或更新。...

    Hibernate_级联关系说明_-_关于cascade和inverse的用法

    在探讨Hibernate框架中的级联操作(cascade)与控制权反转(inverse)之前,我们需要先对Hibernate有一个基本的理解。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用提供了一种将对象模型映射到...

    hibernate_配置cascade_及all-delete-orphan.doc

    在Hibernate框架中,cascade选项提供了一种管理实体间关联的便捷方式,使得对一个实体的操作能够自动地应用到与之相关的其他实体上。这对于处理复杂的数据库关系非常有用,可以极大地简化代码,并减少出错的可能性。...

    关联映射cascade,inverse讲解

    在Java持久化框架Hibernate中,关联映射是数据库表之间的关系在对象模型中的体现,它使得我们可以方便地处理对象与数据库之间的数据交互。本篇将深入讲解“cascade”和“inverse”这两个重要的概念,以及它们在实际...

    Hibernate 对集合属性的操作.zip_hibernate

    - **一对多(OneToMany)**:使用`&lt;list&gt;`、`&lt;set&gt;`或`&lt;bag&gt;`,并通过`inverse`属性指定维护端,`cascade`属性控制级联操作。 - **多对一(ManyToOne)**:通过`&lt;many-to-one&gt;`标签,指定引用的目标实体类以及引用...

    Hibenate cascade

    总之,理解和正确使用`cascade`和`inverse`属性对于优化Hibernate应用程序的性能和数据一致性至关重要。这两个属性的组合使用可以精确地控制对象关系的生命周期管理,确保数据库中的数据与程序中的对象状态保持一致...

    Hibernate开发租房系统2 源码

    描述提到“使用cascade和inverse优化区和街道关联关系”,这意味着我们将深入理解Hibernate的cascade和inverse属性,以及它们在双向一对多关联关系中的应用。 Hibernate是Java领域中广泛使用的对象关系映射(ORM)...

    hibernate

    根据提供的文件信息,我们可以深入探讨Hibernate框架中的几个关键概念,特别是`fetch`, `lazy`, `cascade`, 和 `inverse`关键字的使用与理解。这四个概念在处理对象关系映射(ORM)时非常重要,尤其是在Java环境下...

    hibernate学习笔记

    在Hibernate中,`inverse`属性通常与双向关联的实体一起使用,它决定了哪一方实体在进行删除或更新关联时拥有控制权。例如,在一对多关系中,如果`inverse`属性被设置为`true`,那么这一方将不会主动触发对关联实体...

Global site tag (gtag.js) - Google Analytics