Hibernate的对象识别

1.Hibernate对象的3种状态:

(1)瞬时对象:

由new操作符创建,且尚未与Session 关联的对象被认定为瞬时(Transient)的,不和数据库的数据有任何关联关系。瞬时(Transient)对象没有被持久化到数据库中,也不会被赋予持久化标识(identifier)

如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。 由于此对象没有纳入Session的管理,那么此时该对象的任何变化都不会发出SQL语句。

但是可以用Session的持久方法(save(),saveOrUpdate()等)进行持久化操作时才会转变为持久对象并拥有和数据库记录相同的id标识。

(2)持久对象:

持久(Persistent)对象在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久对象可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 它有持久化管理器Session统一管理,持久对象是在事务中进行操作的——Transaction实例执行commit()之后,与数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句把内存中的状态同步到数据库中。

持久化对象任何变化都会自动地发出SQL语句,也就是说该对象和数据库是实时联动(同步的)。

(3)托管对象:

与持久(Persistent)对象关联的Session被关闭后,对象就变为脱管(Detached)的。 托管表示这个对象不能再与数据库保持同步,它们不再受Session管理。

对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached期间的改动将被持久化到数据库)。

2.Session的get 方法 和 load 方法的区别

(1)如果没有符合条件的纪录,get返回一个null,load会抛出一个ObjectNotFoundException。
(2)get方法立即加载对象, load返回一个代理对象,延迟装载对象,只有在对象第一次被应用程序访问时,Hibernate才会从数据库中加载该对象。

3.对象识别

对数据库而言,其识别一条记录唯一性的方式是根据主键值,如果手上有两条记录,它们拥有同样的主键值,则它们在数据库中代表同一个字段的记录。对Java而言,要识别两个对象是否为同一个对象有两种方式
(1)内存地址识别(“= =”号识别)
(2)根据equals()、hasCode()中的定义 
   (默认Object类中定义的equals(Object o)方法也是按内存地址来比较的),源码如下:
   

public boolean equals(Object obj){
   	      return  (this==obj);
   }
先探讨第一种Java的识别方式在Hibernate中该注意的地方,在Hibernate中,如果是在同一个session中根据相同查询所得到的相同记录,则它们会拥有相同的Java识别

举个实际的例子:

Session session = sessions.openSession();
Person p1 = (Person)session.get(Person.class,1);
Person p2 =(Person)session.get(Person.class,1);
session.close(); 
System.out.println(p1 = = p2);

上面这个程序片段将会显示true的结果,表示p1与p2是参考至同一对象,如果是以下的情况则会显示false:

Session session1 = sessions.openSession();
Person p1 = (Person)session.get(Person.class,1);
session1.close(); 
Session session2 = sessions.openSession();
Person p2 = (Person)session.get(Person.class,1);
session2.close(); 
System.out.println(p1 == p2);

使用==来比较两个对象的记录是否代表数据库中的同一条记录是不可行的。如果您要有必要比较通过查询后两个对象的内容是否相同,必须重写 equals()与hashCode()。 

重写方法之一,equals()与hashCode()的方法是根据数据库的identity,就是透过getId()方法取得对象的id值并加以比较

例子中假设id的类型是String: 

public class Person {    
....     
	  public boolean equals(Object o) {        
if(this == o) 
		return true;       
if(id == null || !(o instanceof Person)) 
		return false;         
final Person person== (Person) o;        
	return this.id.equals(person.getId());    
}     
public int hashCode() {         
return id == null ? System.identityHashCode(this):id.hashcode();    
} 
}

然而上面的例子是个不被鼓励的例子,因为当一个对象被new出来而还没有save()时,它并不会被赋予id值,这时候就不适用这个方法。 另一个比较被采用的方法是根据对象中真正包括的属性值来作比较。

public class Person {    
 ...    
public boolean equals(Object other) {        
if (this == other) return true;        
if (!(other instanceof Person)) 
	return false;         
final Person Person = (Person) other;         
if (! getUsername().equals(Person.getName())) 
	return false;        
if (!getBirthday().equals(Person.getBirthday())) 
	return false;
if (!getBirthday().equals(Person.getBirthday())) 
     return false;        
return true;    
}     
public int hashCode() {        
int result;        
result = getUsername ().hashCode();        
result = 29 * result + getBirthday().hashCode();      
return result;    
} 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值