Hibernate的get和load方法都是用于查询一条记录,但是他们又很大的区别。
1.从加载方法上对比:
get方法不支持延迟加载,而load支持延迟加载。
2.从返回结果上对比:
load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常
get方法检索不到的话会返回null。
3.从检索执行机制上对比:
get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。
来看具体的例子:
首先是一个持久化类:
public class Pet {
private String userName;
private String password;
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
下面是Hibernate的核心配置文件hibernate-cfg.xml代码:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="connection.username">sa</property>
<property name="connection.url">
jdbc:jtds:sqlserver://localhost:1433/epet
</property>
<property name="dialect">
org.hibernate.dialect.SQLServerDialect
</property>
<property name="myeclipse.connection.profile">pet</property>
<property name="connection.driver_class">
net.sourceforge.jtds.jdbc.Driver
</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<mapping resource="com/info/po/Pet.hbm.xml" />
</session-factory>
</hibernate-configuration>
下面是hibernate的另一个配置文件Pet.hbm.xml的代码:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="com.info.po.Pet" table="login">
<id name="id" column="id" type="int">
<generator class="increment"></generator>
</id>
<property name="userName" column="username" type="string"></property>
<property name="password" column="password" type="string"></property>
</class>
</hibernate-mapping>
再就是重要的DAO代码了:
import org.hibernate.Session;
import org.hibernate.Transaction;
public class PetDAO {
public void getPetById(int id){
Session session = HibernateSessionFactory.getSession();
Pet pet = (Pet)session.load(Pet.class, id);
System.out.println(pet.getid());
session.close();
}
}
最后是测试类代码:
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
PetDAO dao = new PetDAO();
dao.getPetById(10);
}
}
数据库里面的表的结构为:
id | username | password |
2 | aaa | 111 |
3 | bbb | 222 |
4 | ccc | 333 |
5 | ddd | 444 |
上面是使用的是get方法,运行以上代码,结果是:
Exception in thread "main" java.lang.NullPointerException
而改用load方法的话,运行发的结果是:
Exception in thread "main" org.hibernate.ObjectNotFoundException
而如果将将上面的dao代码稍微改下,把System.out.println(pet.getId())放到session.close()之后,
public void getPetById(int id){
Session session = HibernateSessionFactory.getSession();
Pet pet = (Pet)session.load(Pet.class, id);
session.close();
System.out.println(pet.getUserName());
}
同样是使用load方法,但是运行的结果却不一样:
Exception in thread "main" org.hibernate.LazyInitializationException
结论:
对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据库中没有就返回null。
需要注意的是:下面这两段代码不会去执行数据库,因为load后会在hibernate的一级缓存中存放一个map对象,该map的key就是id的值,但是当你getId的时候,它会去一级缓存里拿map的key值,而不会去执行数据库查询,也不会保错。
Pet pet = (Pet)session.load(Pet.class, id);
System.out.println(pet.getUserName());
文章最后,附上本文的源代码,如有不对的地方,晴大家多多指正。