对象识别
对数据库而言,其识别一条记录唯一性的方式是根据主键值,如果手上有两条记录,它们拥有同样的主键值,则它们在数据库中代表同一个字段的记录。
对Java而言,要识别两个对象是否为同一个对象有两种方式
内存地址识别(“= =”号识别)
根据equals()、hasCode()中的定义
(默认Object类中定义的equals(Object o)方法也是按内存地址来比较的),源码如下:
public boolean equals(Object obj){
return (this==obj);
}
//String对象识别
public void testStringObjectsIndentify() {
Configuration cfg = null;
SessionFactory sf = null;
Session session = null;
Transaction ts = null;
try {
//使用单例模式创建Configuration对象和Session工厂
sf = HibernateUtil.getSessionFactory();
//保证每个读写线程有唯一的session实例
session = sf.getCurrentSession();
//创建事务
ts = session.beginTransaction();
String a = "abc";
String b = "abc";
System.out.println(a == b);
System.out.println(a.equals(b));
String c = "mnp";
String d = new String("mnp");
System.out.println(c == d);
System.out.println(c.equals(d));
//提交事务
ts.commit();
} catch (Exception e) {
e.printStackTrace();
if(ts != null) {
ts.rollback();
}
}finally {
}
}
//结果:true,true,false,true;String重写equal,比较内容是否相同
(1)先探讨第一种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是参考至同一对象
(2)如果是以下的情况则会显示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()。
//User对象识别
public void testUserObjectsIndentify() {
Configuration cfg = null;
SessionFactory sf = null;
Session session = null;
Transaction ts = null;
User u1 = null,u2 = null;
try {
//使用单例模式创建Configuration对象和Session工厂
sf = HibernateUtil.getSessionFactory();
//保证每个读写线程有唯一的session实例
session = sf.getCurrentSession();
//创建事务
ts = session.beginTransaction();
u1 = session.get(User.class, 2);
//User u2 = session.get(User.class, 2);
//System.out.println(u1 == u2);//同一个session,引用相同
//提交事务
ts.commit();
} catch (Exception e) {
e.printStackTrace();
if(ts != null) {
ts.rollback();
}
}finally {
}
try {
//使用单例模式创建Configuration对象和Session工厂
sf = HibernateUtil.getSessionFactory();
//保证每个读写线程有唯一的session实例
session = sf.getCurrentSession();
//创建事务
ts = session.beginTransaction();
u2 = session.get(User.class, 2);
//提交事务
ts.commit();
} catch (Exception e) {
e.printStackTrace();
if(ts != null) {
ts.rollback();
}
}finally {
}
System.out.println(u1 == u2);
System.out.println(u1.equals(u2));
}
解决办法:根据对象中真正包括的属性值来作比较
重写equals()和hashcode()方法
默认equals()比较的是地址,重写后比较引用
public boolean equals(Object obj) {
//引用相同
if(this == obj) return true;
//没有引用
if(obj == null) return false;
//实例不正确
if(!(obj instanceof User)) return false;
User other = (User)obj;
if(id != other.id) {
return false;
}
if(age != other.age) {
return false;
}
if(!name.equals(other.name)) {
return false;
}
if(gender !=null && other.gender != null)
{
if(!gender.equals(other.gender)) {
return false;
}
}
if(!birthday.equals(other.birthday)){
return false;
}
return true;
}
//通过hash值操作对象
public int hashCode() {
int result;
result = getName().hashCode();
result = 29 * result + getBirthday().hashCode();
result = 29 * result + getAge();
return result;
}