hibernate inverse 作用 inverse="true" 作用

我们引用一个一对多的bag类型关联说明这个问题:
代码:
  1. publicclassItemimplementsSerializable {
  2. privateInteger itemId;
  3. privateString itemName;
  4. privateCollection<Bid> bids =newArrayList<Bid>();


  1. /**
  2. * 出价
  3. * @author partner4java
  4. *
  5. */
  6. publicclassBidimplementsSerializable {
  7. privateInteger bidId;
  8. privateDouble bidMoeny;
  9. privateItem item;


配置文件:

  1. <classname="Item"table="ITEM">
  2. <id name="itemId"column="ITEM_ID"type="integer">
  3. <generatorclass="native"/>
  4. </id>
  5. <property name="itemName"type="string"column="ITEM_NAME"/>
  6. lt;bag name="bids"cascade="save-update">
  7. <!-- 注意column="ITEM_ID_M"名称故意和Item主键不一致,这里是维护端生成的字段名称 -->
  8. <key column="ITEM_ID_M"></key>
  9. <one-to-manyclass="Bid"/>
  10. lt;/bag>
  11. </class>



  1. <classname="Bid"table="BID">
  2. <id name="bidId"column="BID_ID"type="integer">
  3. <generatorclass="native"/>
  4. </id>
  5. <property name="bidMoeny"type="double"></property>
  6. <!-- 注意column="ITEM_ID_M"名称故意和Item主键不一致,这里是说明一的一端的表,需要生成的对应关联字段是什么
  7. KEY `FK100DD8434F24F` (`ITEM_ID_M`),
  8. CONSTRAINT `FK100DD8434F24F` FOREIGN KEY (`ITEM_ID_M`) REFERENCES `item` (`ITEM_ID`) -->
  9. <many-to-one name="item"column="ITEM_ID_M"
  10. class="Item"not-null="true"></many-to-one>
  11. </class>


执行插入:
  1. Item item =newItem("hello");
  2. Bid bid =newBid(12D);
  3. item.getBids().add(bid);
  4. //不添加这个报错:not-null property references a null or transient value(因为添加了不能为空)
  5. //<name="bids" inverse="true" cascade="save-update">也决定了,维护端是Bid的item属性,所以要告诉Bid的item属性item的存在
  6. //要知道这个东西和cascade="save-update"并不想干,cascade只是负责是否级联保存的,和表之间的关系由谁维护无关
  7. bid.setItem(item);
  8. session.save(item);


hibernate打印sql:
Hibernate: insert into ITEM (ITEM_NAME) values (?)
Hibernate: insert into BID (bidMoeny, ITEM_ID_M) values (?, ?)
Hibernate: update BID set ITEM_ID_M=? where BID_ID=?
那么你看到了多打印了一条sql,最后一条是荣誉的。
原因:
在操作两个实例之间的连接时,如果没有inverse属性,hibernate会试图执行两个不同的SQL语句,这两者更新
同一个外键列。通过指定inverse="true",显示地告诉hibernate连接的哪一端不应该与数据库同步。在这个例子
中,告诉hibernate他应该把在关联的Bid端所做的变化传播到数据库,忽略只对bids集合所做的变化。
如下:
  1. <classname="Item"table="ITEM">
  2. <id name="itemId"column="ITEM_ID"type="integer">
  3. <generatorclass="native"/>
  4. </id>
  5. <property name="itemName"type="string"column="ITEM_NAME"/>
  6. lt;bag name="bids"inverse="true"cascade="save-update">
  7. <!-- 注意column="ITEM_ID_M"名称故意和Item主键不一致,这里是维护端生成的字段名称 -->
  8. <key column="ITEM_ID_M"></key>
  9. <one-to-manyclass="Bid"/>
  10. lt;/bag>
  11. </class>

执行相同插入:
hibernate打印sql:
Hibernate: insert into ITEM (ITEM_NAME) values (?)
Hibernate: insert into BID (bidMoeny, ITEM_ID_M) values (?, ?)


那么有些时候,是不能添加inverse="true"的,比如保存有序的list集合:
添加:insert="false" update="false"
但是这么做还是会打印三条sql,不添加则会报错
Repeated column in mapping for entity: cn.partner4java.hibernate.onetomany2.Bid column: ITEM_ID (should be mapped with insert="false" update="false")
如:
  1. <classname="Item"table="ITEM">
  2. <id name="itemId"column="ITEM_ID"type="integer">
  3. <generatorclass="native"/>
  4. </id>
  5. <property name="itemName"type="string"column="ITEM_NAME"/>
  6. <!-- 没有在集合中加入inverse="true,因为hibernate忽略反向集合的状态!
  7. 但是这一次,集合包含了正确的更新数据库所需要的信息:它的元素的位置。
  8. 如果只有每个Bid实例的状态被认为是同步的,集合又是方向的并且被忽略,
  9. 那么hibernate就没有值给BID_POSITOIN了-->
  10. <list name="bids"cascade="save-update">
  11. <key column="ITEM_ID"not-null="true"></key>
  12. <list-index column="BID_POSITOIN"></list-index>
  13. <one-to-manyclass="Bid"/>
  14. </list>
  15. </class>
  16. <classname="Bid"table="BID">
  17. <id name="bidId"column="BID_ID"type="integer">
  18. <generatorclass="native"/>
  19. </id>
  20. <property name="bidMoeny"type="double"></property>
  21. <!-- 如果通过被索引的集合映射双向的一对多实体关联(映射和数组也是这样),
  22. 就必须转换为方向段。无法被索引的集合变成inverse="true"。集合变成了
  23. 负责状态同步,并且一的端Bid必须变成反向。然而,多对一的映射没有
  24. inverse="true",因此需要在<many-to-one>中模拟这一模拟这一属性:
  25. 设置insert="false"update="false"
  26. 这俩个属性一起使用,实际上使属性变成了只读。关联的这一端因此被任何写操作忽略,
  27. 当内存状态与数据库同步时,集合的状态就是相关的状态。你已经转换了关联的方向/非方向端,
  28. 如果从set或者bag转换为list,这个是必要的条件。
  29. -->
  30. <many-to-one name="item"column="ITEM_ID_M"
  31. class="Item"not-null="true"
  32. insert="false"update="false"></many-to-one>
  33. </class>





双向对多对时:
代码:
  1. publicclassCategoryimplementsSerializable {
  2. privateInteger categoryId;
  3. privateString name;
  4. privateSet<Item> items =newHashSet<Item>();


  1. publicclassItemimplementsSerializable {
  2. privateInteger itemId;
  3. privateString itemName;
  4. privateSet<Category> categories =newHashSet<Category>();


配置文件:
  1. <classname="Category"table="Category">
  2. <id name="categoryId"column="CATEGORY_ID"type="integer">
  3. <generatorclass="native"/>
  4. </id>
  5. <property name="name"type="string"column="name"/>
  6. <set name="items"table="CATEGORY_ITEM"inverse="true"cascade="save-update">
  7. <key column="CATEGORY_ID"></key>
  8. <many-to-many column="ITEM_ID"class="Item"></many-to-many>
  9. </set>
  10. </class>

  1. <classname="Item"table="ITEM">
  2. <id name="itemId"column="ITEM_ID"type="integer">
  3. <generatorclass="native"/>
  4. </id>
  5. <property name="itemName"type="string"column="ITEM_NAME"/>
  6. <set name="categories"table="CATEGORY_ITEM"cascade="save-update">
  7. <key column="ITEM_ID"></key>
  8. <many-to-many column="CATEGORY_ID"class="Category"></many-to-many>
  9. </set>
  10. </class>


插入代码:
  1. publicclassHelloWorld {
  2. publicstaticvoidmain(String[] args) {
  3. //insert();
  4. //insert2();
  5. insert3();
  6. }
  7. privatestaticvoidinsert() {
  8. Configuration configuration =newConfiguration().configure();
  9. SessionFactory sessionFactory = configuration.buildSessionFactory();
  10. Session session = sessionFactory.openSession();
  11. Transaction tr = session.beginTransaction();
  12. Item item =newItem("item");
  13. Category category1 =newCategory("category1");
  14. item.getCategories().add(category1);
  15. Category category2 =newCategory("category2");
  16. item.getCategories().add(category2);
  17. session.save(item);
  18. //Hibernate: insert into ITEM (ITEM_NAME) values (?)
  19. //Hibernate: insert into Category (name) values (?)
  20. //Hibernate: insert into Category (name) values (?)
  21. //Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)
  22. //Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)
  23. tr.commit();
  24. session.close();
  25. sessionFactory.close();
  26. }
  27. privatestaticvoidinsert2() {
  28. Configuration configuration =newConfiguration().configure();
  29. SessionFactory sessionFactory = configuration.buildSessionFactory();
  30. Session session = sessionFactory.openSession();
  31. Transaction tr = session.beginTransaction();
  32. Category category =newCategory("category1");
  33. Item item1 =newItem("item1");
  34. category.getItems().add(item1);
  35. Item item2 =newItem("item1");
  36. category.getItems().add(item2);
  37. session.save(category);
  38. //inverse="true"的一端,忽略对中间库的影响
  39. //Hibernate: insert into Category (name) values (?)
  40. //Hibernate: insert into ITEM (ITEM_NAME) values (?)
  41. //Hibernate: insert into ITEM (ITEM_NAME) values (?)
  42. tr.commit();
  43. session.close();
  44. sessionFactory.close();
  45. }
  46. privatestaticvoidinsert3() {
  47. Configuration configuration =newConfiguration().configure();
  48. SessionFactory sessionFactory = configuration.buildSessionFactory();
  49. Session session = sessionFactory.openSession();
  50. Transaction tr = session.beginTransaction();
  51. Category category =newCategory("category1");
  52. Item item1 =newItem("item1");
  53. category.getItems().add(item1);
  54. Item item2 =newItem("item1");
  55. category.getItems().add(item2);
  56. //必须存在,才会影响中间表,因为inverse="false"的一端,才会影响中间库的变化
  57. item1.getCategories().add(category);
  58. item2.getCategories().add(category);
  59. session.save(category);
  60. //Hibernate: insert into Category (name) values (?)
  61. //Hibernate: insert into ITEM (ITEM_NAME) values (?)
  62. //Hibernate: insert into ITEM (ITEM_NAME) values (?)
  63. //Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)
  64. //Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)
  65. tr.commit();
  66. session.close();
  67. sessionFactory.close();
  68. }
  69. }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值