9.7.1. 同步(Flush) Session
如果你正在使用TransactionAPI,你就不用担心这个步骤。在事务提交的时候,隐含就会包括这一步。否则,你应该调用Session.flush()来确保你所有的修改都与数据库同步。
9.7.2. 提交数据库事务
如果你正在使用Hibernate 的Transaction API,代码类似这样:
tx.commit(); // flush the Session and commit the transaction
如果你自行管理JDBC事务,你应该手工对JDBC 连接执行commit()。
sess.flush();
sess.connection().commit(); // not necessary for JTA datasource
如果你决定不提交你的更改:
tx.rollback(); // rollback the transaction
或者:
// not necessary for JTA datasource, important otherwise
sess.connection().rollback();
如果你回滚了事务,你应该立即关闭和取消当前session,确保Hibernate内部状态的完整性。
9.7.3. 关闭Session
调用Session.close()就标志这个session进入了尾声。close()主要的含义就是与这个session相关的JDBC连接会被放弃。
tx.commit();
sess.close();
sess.flush();
sess.connection().commit(); // not necessary for JTA datasource
sess.close();
如果你自行管理连接,close()会返回连接的一个引用,你就可以手工把它关闭,或者返回它到连接池去。其他情况下,close()会把它返回到连接池去。
9.7.4. 处理异常
如果Session抛出了一个exception(包括任何SQLException),你应该立刻回滚这个事务,调用Session.close)()来取消这个Session实例。Session中的一些特定方式会确保session不会处于一个不稳定不完整的状态。
建议采用下面的异常处理片断:
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
// do some work
...
tx.commit();
}
catch (Exception e) {
if (tx!=null) tx.rollback();
throw e;
}
finally {
sess.close();
}
如果你是手工管理JDBC事务的,用下面这段:
Session sess = factory.openSession();
try {
// do some work
...
sess.flush();
sess.connection().commit();
}
catch (Exception e) {
sess.connection().rollback();
throw e;
}
finally {
sess.close();
}
如果你是从JTA中获得数据源的:
UserTransaction ut = .... ;
Session sess = factory.openSession();
try {
// do some work
...
sess.flush();
}
catch (Exception e) {
ut.setRollbackOnly();
throw e;
}
finally {
sess.close();
}
9.8. 生命周期和对象图(Lifecyles and object graphs)
要保存或者更新一个对象关联图中所有的所有对象,你必须做到:
保证每一个对象都执行save(), saveOrUpdate() 或 update()方法,或者,
在定义关联对象的映射时,使用cascade="all"或cascade="save-update"。
类似的,要删除一个关系图中的所有对象,必须:
对每一个对象都执行delete(),或者
在定义关联对象的映射时,使用cascade="all",cascade="all-delete-orphan"或cascade="delete"。
建议:
如果子对象的生命期是绑定到父对象的生命期的,通过指定cascade="all"可以把它变成一个自动管理生命周期的对象(lifecycle object)。
否则,必须在应用程序代码中明确地执行save()和delete()。如果你想少敲一些代码,可以使用cascade="sve-update",然后只需明确地delete()。
对一种关联(多对一,或者集合)使用cascade="all"映射,就把这种关联标记为一种父/子(parent/child)风格的关系,对父对象进行保存/更新/删除会导致对(所有)子对象的保存/更新/删除。但是这个比喻并不是特别确切。如果父对象解除了对某个子对象的关联,那这个子对象就不会被自动删除了。除非这是一个一对多的关联,并且标明了cascade="all-delete-orphan"(所有-删除-孤儿)。级联操作的精确语义在下面列出:
如果父对象被保存,所有的子对象会被传递到saveOrUpdate()方法去执行
如果父对象被传递到update()或者saveOrUpdate(),所有的子对象会被传递到saveOrUpdate()方法去执行
如果一个临时的子对象被一个持久化的父对象引用了,它会被传递到saveOrUpdate()去执行
如果父对象被删除了,所有的子对象对被传递到delete()方法执行
如果临时的子对象不再被持久&# 1270;的父对象引用,什么都不会发生(必要时,程序应该明确的删除这个子对象),除非声明了cascade="all-delete-orphan",在这种情况下,成为“孤儿”的子对象会被删除。
Hibernate还没有完全实现“通过可触及性决定持久化”,后者暗示会对垃圾收集进行(效率不高的)持久化。但是,因为很广泛的呼声,Hibernate实现了一种意见,如果一个实体被一个持久化的对象引用,它也会被持久化。注明了cascade="save-update"的关联就是按照这种思路运作的。如果你希望在你的整个程序中都贯彻这个方法,你可以在<hibernate-mapping>元素的default-cascade属性中指定这种级联方式。