hibernate inverse 作用 inverse="true" 作用

我们引用一个一对多的bag类型关联说明这个问题: 
代码: 
  1. public class Item implements Serializable {  
  2.     private Integer itemId;  
  3.     private String itemName;  
  4.       
  5.     private Collection<Bid> bids = new ArrayList<Bid>();  


  1. /** 
  2. * 出价 
  3. * @author partner4java 
  4. * 
  5. */  
  6. public class Bid implements Serializable {  
  7.     private Integer bidId;  
  8.     private Double bidMoeny;  
  9.       
  10.     private Item item;  


配置文件: 

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



  1.   <class name="Bid" table="BID">  
  2.       <id name="bidId" column="BID_ID" type="integer">  
  3.           <generator class="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 = new Item("hello");  
  2. Bid bid = new Bid(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.   
  9. 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. <class name="Item" table="ITEM">  
  2.      <id name="itemId" column="ITEM_ID" type="integer">  
  3.          <generator class="native"/>  
  4.      </id>  
  5.      <property name="itemName" type="string" column="ITEM_NAME"/>  
  6.        
  7. lt;bag name="bids" inverse="true" cascade="save-update">  
  8. <!-- 注意column="ITEM_ID_M"名称故意和Item主键不一致,这里是维护端生成的字段名称 -->  
  9. <key column="ITEM_ID_M"></key>  
  10. <one-to-many class="Bid"/>  
  11. lt;/bag>  
  12.          
  13. </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.   <class name="Item" table="ITEM">  
  2.       <id name="itemId" column="ITEM_ID" type="integer">  
  3.           <generator class="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-many class="Bid"/>  
  14. </list>                 
  15.   </class>  
  16.   
  17.   
  18.   <class name="Bid" table="BID">  
  19.       <id name="bidId" column="BID_ID" type="integer">  
  20.           <generator class="native"/>  
  21.       </id>  
  22. <property name="bidMoeny" type="double"></property>       
  23. <!-- 如果通过被索引的集合映射双向的一对多实体关联(映射和数组也是这样),  
  24.     就必须转换为方向段。无法被索引的集合变成inverse="true"。集合变成了  
  25.     负责状态同步,并且一的端Bid必须变成反向。然而,多对一的映射没有  
  26.     inverse="true",因此需要在<many-to-one>中模拟这一模拟这一属性:  
  27.     设置insert="false" update="false"  
  28.     这俩个属性一起使用,实际上使属性变成了只读。关联的这一端因此被任何写操作忽略,  
  29.     当内存状态与数据库同步时,集合的状态就是相关的状态。你已经转换了关联的方向/非方向端,  
  30.     如果从set或者bag转换为list,这个是必要的条件。  
  31.      -->  
  32. <many-to-one name="item" column="ITEM_ID_M"   
  33.     class="Item" not-null="true"   
  34.     insert="false" update="false"></many-to-one>          
  35.   </class>  





双向对多对时: 
代码: 
  1. public class Category implements Serializable {  
  2.     private Integer categoryId;  
  3.     private String name;  
  4.     private Set<Item> items = new HashSet<Item>();  


  1. public class Item implements Serializable {  
  2.     private Integer itemId;  
  3.     private String itemName;  
  4.     private Set<Category> categories = new HashSet<Category>();  


配置文件: 
  1. <class name="Category" table="Category">  
  2.     <id name="categoryId" column="CATEGORY_ID" type="integer">  
  3.         <generator class="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. <class name="Item" table="ITEM">  
  2.     <id name="itemId" column="ITEM_ID" type="integer">  
  3.         <generator class="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. public class HelloWorld {  
  2.       
  3.     public static void main(String[] args) {  
  4. //      insert();  
  5.           
  6. //      insert2();  
  7.           
  8.         insert3();  
  9.     }  
  10.   
  11.     private static void insert() {  
  12.         Configuration configuration = new Configuration().configure();  
  13.         SessionFactory sessionFactory = configuration.buildSessionFactory();  
  14.         Session session = sessionFactory.openSession();  
  15.         Transaction tr = session.beginTransaction();  
  16.           
  17.         Item item = new Item("item");  
  18.         Category category1 = new Category("category1");  
  19.         item.getCategories().add(category1);  
  20.         Category category2 = new Category("category2");  
  21.         item.getCategories().add(category2);  
  22.           
  23.           
  24.         session.save(item);  
  25. //      Hibernate: insert into ITEM (ITEM_NAME) values (?)  
  26. //      Hibernate: insert into Category (name) values (?)  
  27. //      Hibernate: insert into Category (name) values (?)  
  28. //      Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)  
  29. //      Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)  
  30.   
  31.           
  32.         tr.commit();  
  33.         session.close();  
  34.           
  35.         sessionFactory.close();  
  36.     }  
  37.       
  38.     private static void insert2() {  
  39.         Configuration configuration = new Configuration().configure();  
  40.         SessionFactory sessionFactory = configuration.buildSessionFactory();  
  41.         Session session = sessionFactory.openSession();  
  42.         Transaction tr = session.beginTransaction();  
  43.           
  44.         Category category = new Category("category1");  
  45.         Item item1 = new Item("item1");  
  46.         category.getItems().add(item1);  
  47.         Item item2 = new Item("item1");  
  48.         category.getItems().add(item2);  
  49.           
  50.           
  51.         session.save(category);  
  52.         //inverse="true"的一端,忽略对中间库的影响  
  53. //      Hibernate: insert into Category (name) values (?)  
  54. //      Hibernate: insert into ITEM (ITEM_NAME) values (?)  
  55. //      Hibernate: insert into ITEM (ITEM_NAME) values (?)  
  56.   
  57.           
  58.         tr.commit();  
  59.         session.close();  
  60.           
  61.         sessionFactory.close();  
  62.     }  
  63.       
  64.     private static void insert3() {  
  65.         Configuration configuration = new Configuration().configure();  
  66.         SessionFactory sessionFactory = configuration.buildSessionFactory();  
  67.         Session session = sessionFactory.openSession();  
  68.         Transaction tr = session.beginTransaction();  
  69.           
  70.         Category category = new Category("category1");  
  71.         Item item1 = new Item("item1");  
  72.         category.getItems().add(item1);  
  73.         Item item2 = new Item("item1");  
  74.         category.getItems().add(item2);  
  75.           
  76.         //必须存在,才会影响中间表,因为inverse="false"的一端,才会影响中间库的变化  
  77.         item1.getCategories().add(category);  
  78.         item2.getCategories().add(category);  
  79.           
  80.         session.save(category);  
  81. //      Hibernate: insert into Category (name) values (?)  
  82. //      Hibernate: insert into ITEM (ITEM_NAME) values (?)  
  83. //      Hibernate: insert into ITEM (ITEM_NAME) values (?)  
  84. //      Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)  
  85. //      Hibernate: insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)  
  86.   
  87.           
  88.         tr.commit();  
  89.         session.close();  
  90.           
  91.         sessionFactory.close();  
  92.     }  
  93. }  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值