持久化对象---hibernate学习笔记

来源:互联网 发布:碧粳米 知乎 编辑:程序博客网 时间:2024/05/19 14:39

Hibernate对持久化类没有太多的要求,但我们还是应该遵守如下规则:

       (1)提供一个无参数的构造器:所有持久化类都应该提供一个无参数的构造器,这个构造器可以不采用public访问控制符、因此提供了无参数的构造器,Hibernate就可以使用Constructor.newInstance()来创建持久化类的实例了。为了方便Hibernate在运行时生成代理,构造器的访问控制符至少是包可见的。

        (2)提供了一个标识属性:标识属性通常映射数据库表的主键字段。这个属性可以是任何的原始类型、原始类型的包装类型、java.lang.String或者java.util.Date。如果使用了数据库表的联合主键,甚至可以用一个用户自定义的类,该类拥有这些类型的属性。当然,也可以不指定任何标识属性,而是在映射文件中直接将多个普通属性映射成一个联合属性,但通常不推荐这么做。

提升:虽然Hibernate可以允许持久化类没有标识符属性,而是让Hibernate内部来追踪对象的识别。但这样做将导致Hibernate许多功能无法使用。而且,Hibernate建议使用可以为空的类型来作为标识属性的类型,因此应该尽1可能避免使用基本数据类型。

        (3)为持久化类的每个属性提供setter和getter方法。

        (4)使用非final的类,在运行时生成代理是Hibernate的一个重要功能。如果持久化类没有实现任何接口的话,Hibernate使用CGLIB生成代理,将无法进行性能优化。还有一个可选的策略,让Hibernate持久化类实现一个所有方法都声明为public的接口,此时将使用JDK的动态代理。同时应该避免子啊非final类声明public final的方法。如果非要使用一个有public final方法的类,你必须通过设置lazy="false"来明确地禁用代理。

        (5)重写equals()和hashCode()方法:如果需要把持久化类的实例放入Set中(当需要进行关联映射时,推荐这么做),则应该为持久化类重写equals()和hashCode()方法。实现equals()/hashCode()最显而易见的方法是比较两个对象标识符的值。如果值相同,则两个对象对应于数据库的同一行,因此它们是相当的。遗憾的是,对采用自动生成标识值的对象不能使用这种方法。Hibernate仅为那些持久化对象指定标识值,一个新创建的实例将不会有任何标识值。因此,如果一个实例没有被保存过,但它又确实在一个Set中,保存它将会给这个对象赋一个标识值。如果equals()和hashCode()是基于标识值实现的,则其hashCode返回值将会发生改变,这将违反Set的规则。

Hibernate持久化对象支持如下几个对象状态:

       瞬态:对象由new操作符创建,且尚未与Hibernate Session关联的对象被认为处于瞬态。瞬态对象不会被持久化到数据库中,也不会被赋予持久化标识。如果程序中失去了瞬态对像的引用,瞬态对象将被垃圾回收机制销毁。使用Hibernate Session可以将其变为持久化状态。

       持久化:持久化实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。持久化的实例可以是刚刚保存的,也可以是刚被加载的。无论哪一种,持久化对象都必须与制定的Hibernate Session关联。Hibernate会检测到处于持久化状态对象的改动,在当前操作完成时将对象数据写回数据库。开发者不需要手动执行UPDATE。

        脱管:某个实例曾经处于持久化状态,但随着与之关联的Session被关闭,该对象就变成托管状态。脱管状态的引用依然有效,对象可继续被修改。如果重新让脱管对象与某个Session关联,这个脱管对象会重新转换为持久化状态,而脱管期间的改动也不会丢失,也可被写入数据库。正是因为这个功能,逻辑上的长事务成为可能,它被称为应用程序事务。即事务可以跨越用户的思考,因为当对象处于脱管状态时,该对象的操作无须锁定数据库,不会造成性能的下降。

改变持久化对象状态的方法  

、让瞬态转变为持久化状态,Hibernate Session提供了几个方法:

(1)Serializable save(Object obj):将obj对象变为持久化状态,该对象的属性将被保存到数据库。

(2)Serializable save(Object obj,Object pk):将obj对象保存到数据库,保存到数据库时,指定主键值。

(3)void persist(Object obj):将obj对象变为持久化状态,该对象的属性将被保存到数据库。

(4)void persist(Object obj,Object pk):将obj对象变为持久化状态,保存到数据库时,指定主键值。

提示:使用persist则保证党它在一个事务外部被调用时,并不立即转换成insert语句,这个功能是很有用的,尤其当我们封装一个长会话流程的时候,persist()方法就显得尤为重要了。

       如果POJO的标识属性是generated(也就是说,指定主键生成器)类型的,那么Hibernate将会在执行save()方法时自动生成标识属性值,并将该标识属性值分配给POJO的对象。如果POJO的标识属性是assigned类型的,或者是复合主键(composite key),那么该标识属性值应当在调用save()之前手动赋予给POJO对象。

二、也可以通过load()方法来加载一个持久化实例,根据持久化类的标识属性值加载持久化实例----其实质是从数据库表加载一条新记录。代码如下

News n = sess.load(News.class,New Integer(pk));

注意:如果我们在类映射文件中指定了延迟加载,则load()方法将会返回一个未初始化的代理对象(可以理解为持久化对象的替身),这个代理对象并没有装载数据记录,直到程序调用该代理对象的某方法时,Hibernate才会去访问数据库。

get()方法与load()方法相似,但get()方法会立刻访问数据库,如果没有对应的记录,get()方法返回null,而不是一个代理对象。

三、对于一个曾经持久化的对象,但已经脱离了session的管理的脱管对象,Hibernate提供了update()、merge()、updateOrSave()等犯法来保存这些修改

1.update(),使用该方法后托管对象再次回到session 的管理下,变为持久化状态

2.updateOrSave()方法,如果不清楚对象是否曾经被持久化过,使用此方法可以自动判断,如果持久化过则update,没有则save

3.merge().和update同,有一点区别就是,执行完merge方法后对象不会变为持久化状态,依旧为托管状态,不再session的管理下

四、使用load或get方法时可以指定一个“锁模式”的参数(可以防止并发问题,但是影响性能),提供READ,UPGRADE两个静态属性来代表共享,修改锁,

比如要加载某个持久化对象:News n = Session.get(News.class,new Integer(pk),LockMode.UPGRADE)

五、lock方法,也可以将某个对象重新持久化,但该脱管对象必须是没有修改过的,

//简单重新持久化

session.lock(news , LockMode.NONE);

//先检查持久化对象的版本,然后重新持久化对象

session.lock(news , LockMode.READ);

//先检查持久化对象的版本,然后使用SELECT...FOR UPDATE重新持久话对象

session.lock(news , LockMode.PESSIMISTIC_WRITE);

六、delete,一旦删除该持久化对象,对应的数据库记录也删除

session.delete(n)




原创粉丝点击