您的位置:首页 > 运维架构

hibernate 一对多,由谁维护性能最优

2016-03-18 13:51 169 查看
举例如下

Customer类:

Java代码


public class Customer {

private int id;

private String name;

private Set orders = new HashSet();

•••

}

即Customer类具有一个set集合属性orders,其中Order是一个普通的类:

Java代码


public class Order {

private int id;

private String orderName;

•••

}

数据库中表的结构:

Java代码


t_customer: 两个字段:id name

t_order: 三个字段:id orderName customerid

Customer类的映射文件:Customer.hbm.xml (Order类的映射文件忽略)

Java代码


<hibernate-mapping>

<class name="test.Customer" table="t_customer" lazy="false">

<id name="id">

<generator class="native"/>

</id>

<property name="name"/>

<set name="orders" cascade="save-update" lazy="false">

<key column="customerid"/>

<one-to-many class="test.Order"/>

</set>

</class>

</hibernate-mapping>

执行如下代码:

Java代码


Set orders = new HashSet();

Order o1 = new Order();

o1.setOrderName("o1");

Order o2 = new Order();

o2.setOrderName("o2");

orders.add(o1);

orders.add(o2);

Customer c = new Customer();

c.setName("aaa");

c.setOrders(orders);

session.save(c);

此时Hibernate发出的sql语句如下:

Java代码


Hibernate: insert into t_customer (name) values (?)

Hibernate: insert into t_order (orderName) values (?)

Hibernate: insert into t_order (orderName) values (?)

Hibernate: update t_order set customerid=? where id=?

Hibernate: update t_order set customerid=? where id=?

查看数据库:

Java代码


t_customer : t_order:

id | name id | orderName | customerid

1 aaa 1 o1 1

2 o2 1

保存Customer对象时,首先发出insert into t_customer (name) values (?)语句将c同步到数据库,由于在<set>映射中设置cascade="save-update",所以会同时保存orders集合中的Order类型的o1,o2对象(如果没有这个设置,即cascade="save-update"),那么Hibenrate不会自动保存orders集合中的对象,那么在更新时将会抛出如下异常:

Java代码


Hibernate: insert into t_customer (name) values (?)

Hibernate: update t_order set customerid=? where id=?

org.hibernate.TransientObjectException: test.Order

••••••

抛出这一异常的原因是:<set>映射默认"inverse=fasle"即由Customer对象作为主控方,那么它要负责关联的维护工作,在这里也就是负责更新t_order表中的customerid字段的值,但由于未设置cascade="save-update",所以orders集合中的对象不会在保存customer时自动保存,因此会抛出异常(如果未设置,需要手动保存)。
现在设置cascade="save-update",同时设置inverse="true",即:

Java代码


•••

<set name="orders" cascade="save-update" inverse="true" lazy="false">

<key column="customerid"/>

<one-to-many class="test.Order"/>

</set>

•••

同样执行上述代码,发出如下语句:

Java代码


Hibernate: insert into t_customer (name) values (?)

Hibernate: insert into t_order (orderName) values (?)

Hibernate: insert into t_order (orderName) values (?)

相比上一次执行,少了两条update语句,查看数据库:

Java代码


t_customer : t_order:

id | name id | orderName | customerid

1 aaa 1 o1 NULL

2 o2 NULL

发现t_order表中customerid的值为NULL,这是由于设置了inverse="true",它意味着
Customer不再作为主控方,而将关联关系的维护工作交给关联对象Orders来完成。在保存Customer时,Customer不在关心Orders的customerid属性,必须由Order自己去维护,即设置order.setCustomer(customer);

如果需要通过Order来维护关联关系,那么这个关联关系转换成双向关联。
修改Order类代码:

Java代码


public class Order {

private int id;

private String orderName;

private Customer customer;

•••

}

Order.hbm.xml:

Java代码


<hibernate-mapping>

<class name="test.Order" table="t_order">

<id name="id">

<generator class="native"/>

</id>

<property name="orderName"/>

<many-to-one name="customer" column="customerid"/>

</class>

</hibernate-mapping>

此时数据库中表的结构不会变化。

再次执行上述代码,发出如下sql语句:

Java代码


Hibernate: insert into t_customer (name) values (?)

Hibernate: insert into t_order (orderName, customerid) values (?, ?)

Hibernate: insert into t_order (orderName, customerid) values (?, ?)

发现在保存Order对象时为customerid字段赋值,因为Order对象中拥有Customer属性,对应customerid字段,查看数据库表:

Java代码


t_customer : t_order:

id | name id | orderName | customerid

1 aaa 1 o1 NULL

2 o2 NULL

发现customerid的值仍为NULL,因为在上述代码中并未设置Order对象的Customer属性值,由于设置了inverse="true",所以Order对象需要维护关联关系,所以必须进行设置,即
order.setCustomer(customer);

修改上述代码为:

Java代码


•••

Customer c = new Customer();

Set orders = new HashSet();

Order o1 = new Order();

o1.setOrderName("o1");

o1.setCustomer(c);

Order o2 = new Order();

o2.setOrderName("o2");

o2.setCustomer(c);

orders.add(o1);

orders.add(o2);

c.setName("aaa");

c.setOrders(orders);

session.save(c);

•••

执行上述代码,发出如下语句:

Java代码


Hibernate: insert into t_customer (name) values (?)

Hibernate: insert into t_order (orderName, customerid) values (?, ?)

Hibernate: insert into t_order (orderName, customerid) values (?, ?)

查看数据库:

Java代码


t_customer : t_order:

id | name id | orderName | customerid

1 aaa 1 o1 1

2 o2 1

发现已经设置了customerid的值。

在一对多关联中,在一的一方设置inverse="true"(即由多来维护!!),有助于性能的改善。通过上述分析可以发现少了update语句。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: