在Hibernate下,实体类将collection作为自己的一个逻辑单元,而不是被容纳的多个实体。这非常重要!它主要体现为以下几点:
-
当删除或增加collection中对象的时候,拥有这个collection的实体对象的版本值会递增。
-
如果一个从collection中移除的对象是一个值类型(value type)的实例,比如composite element,那么这个对象的持久化状态将会终止,其在数据库中对应的记录会被删除。同样的,向collection增加一个value type的实例将会使之立即被持久化。
-
另一方面,如果从一对多或多对多关联的collection中移除一个实体,在缺省情况下这个对象并不会被删除。这个行为是完全合乎逻辑的--改变一个实体的内部状态不应该使与它关联的实体消失掉!同样的,向collection增加一个实体不会使之被持久化。
实际上,向Collection增加一个实体的缺省动作只是在两个实体之间创建一个连接而已,同样移除的时候也只是删除连接。这种处理对于所有的情况都是合适的。不适合所有情况的其实是父子关系本身,因为子对象是否存在依赖于父对象的生存周期。
3. 级联与未保存值(Cascades and unsaved-value)
假设我们从Session中装入了一个Parent对象,用户界面对其进行了修改,然后我们希望在一个新的Session里面调用update()来更新它。对象Parent包含了子对象的集合,由于打开了级联更新,Hibernate需要知道哪些子对象是新的,哪些是数据库中已经存在的。我们假设Parent和Child对象的标识属性都是自动生成的,类型为java.lang.Long。Hibernate会使用标识属性的值,和version 或 timestamp 属性,来判断哪些子对象是新的,在 Hibernate3 中,显式指定unsaved-value不再是必须的了。
下面的代码会更新parent和child对象,并且插入newChild对象。
//parent and child were both loaded in a previous session
parent.addChild(child);
Child newChild = new Child();
parent.addChild(newChild);
session.update(parent);
session.flush();
好的,对于自动生成标识的情况这样做很方便,但是自分配的标识和复合标识怎么办呢?这是有点麻烦,因为Hibernate没有办法区分新对象(标识被用户指定了)和前一个Session装入的对象。在这种情况下,Hibernate会使用timestamp或version属性,或者查询第二级缓存,或者最坏的情况,查询数据库,来确认是否此行存在。
这个问题往往让新手感到迷惑,它确实不太容易消化。不过,经过一些实践以后,你会感觉越来越顺手。父子对象模式已经被广泛的应用在Hibernate应用程序中。
发表于 @ 2008年03月26日 16:56:00|评论(loading...)|编辑