hibernate关联
??? <id name="id" type="long" column="ID">
????? <generator type="string" >
??????? <column name="NAME" length="15" />
??? </property>
?????
</class>
?
</hibernate-mapping>
?
?
Order.hbm.xml如下:
?
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
?
?? <class name="mypack.Order" table="ORDERS">
????
????? <id name="id" type="long" column="ID">
??????? <generator type="string" >
??????? <column name="ORDER_NUMBER" length="15" />
????? </property>
?
???? <many-to-one
??????? name="customer"
??????? column="CUSTOMER_ID"
??????? table="CUSTOMERS" >
??? <id name="id" type="long" column="ID">
????? <generator type="string" >
??????? <column name="NAME" length="15" />
??? </property>
?
??? <set
??????? name="orders"
??????? cascade="save-update"
??????
??????? >
???????
??????? <key column="CUSTOMER_ID" />
??????? <one-to-many />
???? </set>??
</class>
</hibernate-mapping>
?
<set>元素还包含两个子元素:<key>和<one-to-many>,<one-to-many>元素设定所关联的持久化类,此处为Order类,<key>元素设定与所关联的持久化对应的表的外键,此处为ORDERS表的CUSTOMERS_ID字段。
它包括如下属性:
● <set>元素表明Customer类的orders属性为java.util.Set集合类型。
● <one-to-many>表明orders集合中存放的是一组Order对象。
● <key>属性表明ORDERS表通过外键CUSTOMERS_ID参照CUSTOMERS表。
● cascade 属性取值为"save-update",表明当保存或更新Customer对象时,会级联保存或更新orders集合中的所有Order对象。??
?
接下来我们持久化一个Customer对象以及和他关联的Order对象:
?
????????????? Session session = sessionFactory.openSession();
????????? Transaction tx = null;
?????????? tx = session.beginTransaction();
??????????? Customer customer=new Customer("Tom",new HashSet());
????????? Order order=new Order();
????????? order.setOrderNumber("Tom_Order001");
??????????? order.setCustomer(customer);
????????? customer.getOrders().add(order);
??????????? session.save(customer);
????????? tx.commit();
?
当<set>元素的cascade属性为"save-update"时,Hibernate在持久化Customer对象时,会自动持久化关联的Order对象。
?
如果是加载持久化对象,然后再建立关联关系,那又该怎么做呢?如下所示:
?
Session session = sessionFactory.openSession();
Transaction tx = null;
tx = session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(2));
Order order=(Order)session.load(Order.class,new Long(2));
order.setCustomer(customer);
customer.getOrders().add(order);
tx.commit();
?
Hibernate会自动清理缓存中的所有持久化对象,按照持久化对象状态改变来同步更新数据库,Hibernate在清理以上Customer对象和Order对象时执行了以下两条SQL语句:
???? update ORDERS set ORDER_NUMBER='Jack_Order001',CUSTOMER_ID=2 where ID=2;
?????? update ORDERS set CUSTOMER_ID=2 where ID=2;
尽管只是修改了ORDERS表的一条记录,但是以上SQL语句表明Hibernate执行了两次update操作这是因为HIbernate根据内存中持久化对象的状态变化来决定需要执行的SQL语句,order.setCustomer(customer)执行的相应SQL语句为:
update ORDERS set ORDER_NUMBER='Jack_Order001',CUSTOMER_ID=2 where ID=2;
customer.getOrders().add(order)执行的相应SQL语句为:
update ORDERS set CUSTOMER_ID=2 where ID=2;
重复执行对于的SQL语句会影响应用程序的性能,那么解决的办法是把<set>元素的inverse属性设置为true,默认为false:
?
<set
??????? name="orders"
??????? cascade="save-update"
????????? inverse="ture"
??????? >
???????
??????? <key column="CUSTOMER_ID" />
??????? <one-to-many />
???? </set>
因此在映射一对多双向关联关系时,应该在"one"方把inverse属性设为“ture”,这样可以提高性能。