使一個游離對象轉變為持久化對象。例如以下代碼在session1中保存了一個Customer對象,然后在session2中更新這個Customer對象:
Customer customer = new Customer();
customer.setName("Tom");
Session session1 = sessionFactory.buildSession();
Transaction tx1 = session.beginTransaction();
session1.save(customer);
tx1.commit();
session1.close();
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
customer.setName("Linda"); // 在和session2關聯之前修改Customer對象的屬性
session2.update(customer);
customer2.setName("Jack"); // 在和session2關聯之后修改Customer對象的屬性
tx2.commit();
session2.close();
Session的update()方法完成以下操作:
(1)把Customer對象重新加入到Session的緩存中,使它變為持久化對象。
(2)計划執行一個update語句。值得注意的是,Session只有在清理緩存的時候才會執行update語句,並且在執行時才會把Customer對象當前的屬性值組裝到update語句中。因此,即使程序中多次修改了Customer對象的屬性,在清理緩存時只會執行一次update語句。以下兩段代碼是等價的,無論是左邊的代碼,還是右邊的代碼,Session都只會執行一條update語句:
...... Session session2 = sessionFactory.openSession(); Transaction tx2 = session2.beginTransaction(); customer2.setName("Linda"); session.update(customer); customer.setName("Jack"); tx2.commit(); session2.close(); |
...... Session session2 = sessionFactory.openSession(); Transaction tx2 = session1.beginTransaction(); session2.update(customer); customer.setName("Linda"); customer.setName("Jack"); txt2.commit(); session2.close(); |
以上代碼盡管把Customer對象的name屬性修改了兩次,但Session在清理緩存時,根據Customer對象的當前屬性值來組裝update語句,因此執行的update語句為:
update CUSTOMERS set name='Jack' ...... where ID=1;
只要通過update()方法使游離對象被一個Session關聯,即使沒有修改Customer對象的任何屬性,Session在清理緩存時也會執行由update()方法計划的update語句。例如以下程序使Customer對象被session2關聯,但是沒有修改Customer對象的任何屬性:
// 此處省略session1持久化Customer對象的代碼
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
session.update(customer);
txt2.commit();
session2.close();
Session在清理存緩時,會執行由update()方法計划的update語句,並且根據Customer對象的當前屬性來組裝update語句:
update CUSTOMERS set name='Tom' ...... where ID=1;
如果希望Session僅僅當修改了Customer對象的屬性時,才執行update語句,可以把映射文件中<class>元素的select-before-update設為true,該屬性默認值為false:
<class name="Customer" table="CUSTOMERS" selecet-before-update="true">
如果按以上方式修改了Customer.hbm.xml文件,當Session清理緩存時,會先執行一條select語句:
select * from CUSTOMERS where ID=1;
然后比較Customer對象的屬性是否和從數據庫中檢索出來的記錄一致,只有在不一致的情況下,才執行update語句。
應用根據實際情況來決定是否應該把select-before-update設為true。如果Java對象的屬性不會經常變化,可以把select-before-update屬性設為true,避免Session執行不必要的update語句,這樣會提高應用程序的性能。如果需要經常修改Java對象的屬性,就沒必要把這個屬性設為true,因為它會導致在執行update語句之前,執行一條多余的select語句。
當update()方法關聯一個游離對象時,如果在Session的緩存中已經存在相同OID的持久化對象,會拋出異常。例如以下代碼通過session2加載了OID為1的Customer對象,接下來又試圖把一個OID為1的Customer游離對象加入到session2的緩存中:
// 此處省略session1持久化Customer對象的代碼
......
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
// session2加載一個OID為1的Customer持久化對象
Customer anotherCustomer = (Customer)session2.load(Customer.class, new Long(1));
// 把一個OID為1的Customer游離對象加入到session2的緩存中
session2.update(customer);
tx2.commit();
session2.close();
當執行session2的update()方法時,由於session2的緩存中已經存在了OID為1的Customer持久化對象,因此不允許把OID為1的Customer游離對象再加入到session2的緩存中,Session在運行時會拋出異常。此外,當update()方法關聯一個游離對象時,如果在數據庫中不存在相應的記錄,也會拋出異常。