您的位置:首页 > 产品设计 > UI/UE

Hibernate inverse 作用 inverse="true" 作用

2012-02-01 16:17 453 查看
我们引用一个一对多的bag类型关联说明这个问题:

代码:

view
plaincopy
to clipboardprint?

public class Item implements Serializable
{

private Integer
itemId;

private String
itemName;

private Collection<Bid>
bids = new ArrayList<Bid>();

view
plaincopy
to clipboardprint?

/**

*
出价

*
@author partner4java

*

*/

public class Bid implements Serializable
{

private Integer
bidId;

private Double
bidMoeny;

private Item
item;

配置文件:

view
plaincopy
to clipboardprint?

<class name="Item" table="ITEM">

<id name="itemId" column="ITEM_ID" type="integer">

<generator class="native"/>

</id>

<property name="itemName" type="string" column="ITEM_NAME"/>

lt;bag
name="bids" cascade="save-update">

<!--
注意column="ITEM_ID_M"名称故意和Item主键不一致,这里是维护端生成的字段名称
-->

<key
column="ITEM_ID_M"></key>

<one-to-many class="Bid"/>

lt;/bag>

</class>

view
plaincopy
to clipboardprint?

<class name="Bid" table="BID">

<id
name="bidId" column="BID_ID" type="integer">

<generator class="native"/>

</id>

<property
name="bidMoeny" type="double"></property>

<!--
注意column="ITEM_ID_M"名称故意和Item主键不一致,这里是说明一的一端的表,需要生成的对应关联字段是什么

KEY
`FK100DD8434F24F` (`ITEM_ID_M`),

CONSTRAINT
`FK100DD8434F24F` FOREIGN KEY (`ITEM_ID_M`) REFERENCES `item` (`ITEM_ID`) -->

<many-to-one
name="item" column="ITEM_ID_M"

class="Item" not-null="true"></many-to-one>

</class>

执行插入:

view
plaincopy
to clipboardprint?

Item
item = new Item("hello");

Bid
bid = new Bid(12D);

item.getBids().add(bid);

//不添加这个报错:not-null
property references a null or transient value(因为添加了不能为空)

//<name="bids"
inverse="true" cascade="save-update">也决定了,维护端是Bid的item属性,所以要告诉Bid的item属性item的存在

//要知道这个东西和cascade="save-update"并不想干,cascade只是负责是否级联保存的,和表之间的关系由谁维护无关

bid.setItem(item);

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集合所做的变化。

如下:

view
plaincopy
to clipboardprint?

<class name="Item" table="ITEM">

<id name="itemId" column="ITEM_ID" type="integer">

<generator class="native"/>

</id>

<property name="itemName" type="string" column="ITEM_NAME"/>

lt;bag
name="bids" inverse="true" cascade="save-update">

<!--
注意column="ITEM_ID_M"名称故意和Item主键不一致,这里是维护端生成的字段名称
-->

<key
column="ITEM_ID_M"></key>

<one-to-many class="Bid"/>

lt;/bag>

</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")

如:

view
plaincopy
to clipboardprint?

<class name="Item" table="ITEM">

<id
name="itemId" column="ITEM_ID" type="integer">

<generator class="native"/>

</id>

<property
name="itemName" type="string" column="ITEM_NAME"/>

<!--
没有在集合中加入inverse="true,因为hibernate忽略反向集合的状态!

但是这一次,集合包含了正确的更新数据库所需要的信息:它的元素的位置。

如果只有每个Bid实例的状态被认为是同步的,集合又是方向的并且被忽略,

那么hibernate就没有值给BID_POSITOIN了-->

<list
name="bids" cascade="save-update">

<key
column="ITEM_ID" not-null="true"></key>

<list-index
column="BID_POSITOIN"></list-index>

<one-to-many class="Bid"/>

</list>

</class>

<class name="Bid" table="BID">

<id
name="bidId" column="BID_ID" type="integer">

<generator class="native"/>

</id>

<property
name="bidMoeny" type="double"></property>

<!--
如果通过被索引的集合映射双向的一对多实体关联(映射和数组也是这样),

就必须转换为方向段。无法被索引的集合变成inverse="true"。集合变成了

负责状态同步,并且一的端Bid必须变成反向。然而,多对一的映射没有

inverse="true",因此需要在<many-to-one>中模拟这一模拟这一属性:

设置insert="false" update="false"

这俩个属性一起使用,实际上使属性变成了只读。关联的这一端因此被任何写操作忽略,

当内存状态与数据库同步时,集合的状态就是相关的状态。你已经转换了关联的方向/非方向端,

如果从set或者bag转换为list,这个是必要的条件。

-->

<many-to-one
name="item" column="ITEM_ID_M"

class="Item" not-null="true"

insert="false" update="false"></many-to-one>

</class>

双向对多对时:

代码:

view
plaincopy
to clipboardprint?

public class Category implements Serializable
{

private Integer
categoryId;

private String
name;

private Set<Item>
items = new HashSet<Item>();

view
plaincopy
to clipboardprint?

public class Item implements Serializable
{

private Integer
itemId;

private String
itemName;

private Set<Category>
categories = new HashSet<Category>();

配置文件:

view
plaincopy
to clipboardprint?

<class name="Category" table="Category">

<id
name="categoryId" column="CATEGORY_ID" type="integer">

<generator class="native"/>

</id>

<property
name="name" type="string" column="name"/>

<set
name="items" table="CATEGORY_ITEM" inverse="true" cascade="save-update">

<key
column="CATEGORY_ID"></key>

<many-to-many
column="ITEM_ID" class="Item"></many-to-many>

</set>

</class>

view
plaincopy
to clipboardprint?

<class name="Item" table="ITEM">

<id
name="itemId" column="ITEM_ID" type="integer">

<generator class="native"/>

</id>

<property
name="itemName" type="string" column="ITEM_NAME"/>

<set
name="categories" table="CATEGORY_ITEM" cascade="save-update">

<key
column="ITEM_ID"></key>

<many-to-many
column="CATEGORY_ID" class="Category"></many-to-many>

</set>

</class>

插入代码:

view
plaincopy
to clipboardprint?

public class HelloWorld
{

public static void main(String[]
args) {

// insert();

// insert2();

insert3();

}

private static void insert()
{

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

SessionFactory
sessionFactory = configuration.buildSessionFactory();

Session
session = sessionFactory.openSession();

Transaction
tr = session.beginTransaction();

Item
item = new Item("item");

Category
category1 = new Category("category1");

item.getCategories().add(category1);

Category
category2 = new Category("category2");

item.getCategories().add(category2);

session.save(item);

// Hibernate:
insert into ITEM (ITEM_NAME) values (?)

// Hibernate:
insert into Category (name) values (?)

// Hibernate:
insert into Category (name) values (?)

// Hibernate:
insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)

// Hibernate:
insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)

tr.commit();

session.close();

sessionFactory.close();

}

private static void insert2()
{

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

SessionFactory
sessionFactory = configuration.buildSessionFactory();

Session
session = sessionFactory.openSession();

Transaction
tr = session.beginTransaction();

Category
category = new Category("category1");

Item
item1 = new Item("item1");

category.getItems().add(item1);

Item
item2 = new Item("item1");

category.getItems().add(item2);

session.save(category);

//inverse="true"的一端,忽略对中间库的影响

// Hibernate:
insert into Category (name) values (?)

// Hibernate:
insert into ITEM (ITEM_NAME) values (?)

// Hibernate:
insert into ITEM (ITEM_NAME) values (?)

tr.commit();

session.close();

sessionFactory.close();

}

private static void insert3()
{

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

SessionFactory
sessionFactory = configuration.buildSessionFactory();

Session
session = sessionFactory.openSession();

Transaction
tr = session.beginTransaction();

Category
category = new Category("category1");

Item
item1 = new Item("item1");

category.getItems().add(item1);

Item
item2 = new Item("item1");

category.getItems().add(item2);

//必须存在,才会影响中间表,因为inverse="false"的一端,才会影响中间库的变化

item1.getCategories().add(category);

item2.getCategories().add(category);

session.save(category);

// Hibernate:
insert into Category (name) values (?)

// Hibernate:
insert into ITEM (ITEM_NAME) values (?)

// Hibernate:
insert into ITEM (ITEM_NAME) values (?)

// Hibernate:
insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)

// Hibernate:
insert into CATEGORY_ITEM (ITEM_ID, CATEGORY_ID) values (?, ?)

tr.commit();

session.close();

sessionFactory.close();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息