hibernate中get()与load()的区别
好久没用hibernate,好多东西都忘了,今天就来写写get()和load()的区别。
下面用代码来说明:
先建两个实体类,街道类(Jd)和区县类(Qx)是多对一关系。
Jd:
1 package com.Dto; 2 3 public class Jd { 4 5 private int jdid; 6 private String jdname; 7 private Qx qx=new Qx(); 8 public int getJdid() { 9 return jdid; 10 } 11 public void setJdid(int jdid) { 12 this.jdid = jdid; 13 } 14 public Jd(int jdid, String jdname, Qx qx) { 15 super(); 16 this.jdid = jdid; 17 this.jdname = jdname; 18 this.qx = qx; 19 } 20 public Jd() { 21 super(); 22 // TODO Auto-generated constructor stub 23 } 24 @Override 25 public String toString() { 26 return "Jd [jdid=" + jdid + ", jdname=" + jdname + ", qx=" + qx 27 + "]"; 28 } 29 public String getjdname() { 30 return jdname; 31 } 32 public void setjdname(String jdname) { 33 this.jdname = jdname; 34 } 35 public Qx getQx() { 36 return qx; 37 } 38 public void setQx(Qx qx) { 39 this.qx = qx; 40 } 41 42 }
Jd的实体配置文件(Jd.hbm.xml):
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.Dto.Jd" catalog="test" table="jd"> 7 8 <id name="jdid" type="java.lang.Integer"> 9 <column name="jdid" /> 10 <generator class="native" /> 11 </id> 12 13 <property name="jdname" type="java.lang.String"> 14 <column name="jdname" length="80" /> 15 </property> 16 17 <many-to-one name="qx" class="com.Dto.Qx"> 18 <column name="qxid"></column> 19 </many-to-one> 20 </class> 21 22 </hibernate-mapping>
Qx:
1 package com.Dto; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 public class Qx { 7 8 private int qxid; 9 private String qxname; 10 private Set<Jd> jds =new HashSet<Jd>(); 11 public int getQxid() { 12 return qxid; 13 } 14 public void setQxid(int qxid) { 15 this.qxid = qxid; 16 } 17 public String getQxname() { 18 return qxname; 19 } 20 public void setQxname(String qxname) { 21 this.qxname = qxname; 22 } 23 public Set<Jd> getJds() { 24 return jds; 25 } 26 public void setJds(Set<Jd> jds) { 27 this.jds = jds; 28 } 29 @Override 30 public String toString() { 31 return "Qx [qxid=" + qxid + ", qxname=" + qxname + ", jds=" + jds + "]"; 32 } 33 public Qx(int qxid, String qxname, Set<Jd> jds) { 34 super(); 35 this.qxid = qxid; 36 this.qxname = qxname; 37 this.jds = jds; 38 } 39 public Qx() { 40 super(); 41 // TODO Auto-generated constructor stub 42 } 43 44 }
Qx的实体配置文件(Qx.hbm.xml);
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="com.Dto.Qx" catalog="test" table="qx"> 7 <id name="qxid" type="java.lang.Integer"> 8 <column name="qxid" /> 9 <generator class="native" /> 10 </id> 11 12 <property name="qxname" type="java.lang.String"> 13 <column name="qxname" length="80" /> 14 </property> 15 16 <set name="jds" > 17 <key column="qxid"></key> 18 <one-to-many class="com.Dto.Jd" /> 19 </set> 20 </class> 21 22 </hibernate-mapping>
hibernate配置文件(hibernate.cfg.xml):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory name="mySessionFactory"> 7 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 8 <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8</property> 9 <property name="hibernate.connection.username">root</property> 10 <property name="hibernate.connection.password">root</property> 11 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 12 <property name="hibernate.show_sql">true</property> 13 <property name="hibernate.hbm2ddl.auto">update</property> 14 15 <mapping resource="com/Dto/Jd.hbm.xml" /> 16 <mapping resource="com/Dto/Qx.hbm.xml" /> 17 </session-factory> 18 19 </hibernate-configuration>
建一个获取sessionfactory的类HibernateSessionFactory:
1 package com.until; 2 3 import org.hibernate.SessionFactory; 4 import org.hibernate.cfg.Configuration; 5 6 public class HibernateSessionFactory { 7 8 private static SessionFactory sessionFactory; 9 static{ 10 Configuration config=new Configuration().configure(); 11 sessionFactory=config.buildSessionFactory(); 12 } 13 public static SessionFactory getSessionFactory(){ 14 return sessionFactory; 15 } 16 }
Dao这里就不写了,现在数据库里表中没有数据:
Session session=HibernateSessionFactory.getSessionFactory().openSession();
1.当执行如下语句时:并没有生成sql语句。
Jd jd1=(Jd) session.load(Jd.class, 0);
2.当执行上述相同语句,但在Jd.hbm.xml配置文件中,“<class name="com.Dto.Jd" catalog="test" table="jd" lazy="false">”中加上lazy="false"时:
生成了sql语句,但同时报错:“ org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.Dto.Jd#0]”
3.当执行如下语句时:
Jd jd1=(Jd) session.load(Jd.class, 0);
jd1.getjdname();
生成了sql语句,同时报错:“org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.Dto.Jd#0]”
4.当街道表中有该id对应的数据时,就不会报上述错误。
5.当执行如下语句时:
Jd jd2=(Jd) session.get(Jd.class, 0);
生成了sql语句:“Hibernate: select jd0_.jdid as jdid0_0_, jd0_.jdname as jdname0_0_, jd0_.qxid as qxid0_0_ from test.jd jd0_ where jd0_.jdid=?”
通过上诉代码总结:
1.get和load是根据id取得一个记录
2.load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常,get方法检索不到的话会返回null。
3.get方法直接从数据库中检索,而load方法的执行则比较复杂首先查找session的persistent Context中是否有缓存,如果有则直接返回 如果没有则判断是否是lazy,如果不是直接访问数据库检索,查到记录返回,查不到抛出异常 如果是lazy则需要建立代理对象,对象的initialized属性为false,target属性为null 在访问获得的代理对象的属性时,检索数据库,如果找到记录则把该记录的对象复制到代理对象的target上,并将initialized=true,如果 找不到就抛出异常。
总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,采用立即加载方式,hibernate一定要获取到真实的数据,否则返回null。