在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一个实体对象时是有区别的,在查询性能上两者是不同的。
一.load加载方式
当使用load方法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,即:当我们使用session.load()方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的id值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出sql语句,从数据库中去查询我们的对象。
public UserEntity findById(int uId) throws Exception { Session session=HibernateSessionFactory.getSession(); //get 和 load的区别load可以找缓存,而get不会 UserEntity user=(UserEntity) session.load(UserEntity.class, uId); HibernateSessionFactory.closeSession(); return user; }
调用查询结果时
public class Test {
public static void main(String[] args) {
IUserDao dso=new UserDaoImpl();
UserEntity user2=dso.findById(2);
System.out.println(user2.getUserName());
{
控制台会报错:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) at com.project.entity.UserEntity_$$_jvst43d_1.getUserName(UserEntity_$$_jvst43d_1.java) at com.project.test.Test.main(Test.java:43)
主要原因是因为:
UserEntity user=(UserEntity) session.load(UserEntity.class, uId);是从缓存中获取数据,当要获取对象的属性时才执行sql语句,
但这个时候 HibernateSessionFactory.closeSession();session已关闭就无法完成查询语句,所有会报这个错could not initialize proxy - no Session
解决方式:HibernateSessionFactory.closeSession();等所有的操作完成后再关闭,或者用get方式来获取:UserEntity user=(UserEntity) session.get(UserEntity.class, uId);
二、get加载方式
相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来:
三、懒加载 和 急加载的区别:
懒加载:FathType.LAZY :在加载一个实体的时候,不会马上从数据库加载,即从数据库加载到内存。
急加载:FathType.EAGER:在加载一个实体时会立即从数据库中查询,与其关联的类也会被同时查询。
在我们使用@ManyToOne等时,都会被默认为急加载。
在hibernate中,我们无论是使用懒加载还是急加载,get方法都会一次加载所有基本数据类型属性的值,而load则不同。
在我们开启了懒加载之后,load方法只会加载id属性,所有的非id属性的访问操作都不会执行。只有id属性中有实际值(其实就是你调用load方法时传的那个),
在session没有关闭的之前,如果访问除id外的其他属性才会发sql语句去查询,我们经常犯的一个错误就是在当前session关闭以后访问由load()加载的对象的非id属性,
此时Hibernate尝试通过当前session发sql查询,但发现session已经关闭,这样就会发出no session的异常 。
一般我们将FetchType.lazy 改成 EAGER ,就可以避免这个错误。
但是在我们需要查询一个表时,如果这个表有很多与其关联的表,如果使用急加载的话,在第一次加载就会很慢,如果是懒加载相对则会快一些。但是在我们又需要查询与此表相关的数据的时候,急加载就会很快,因为在第一次加载的时候,已经帮我们全部加载好了。而懒加载则会相对慢一些,因为在我门需要查询的时候,它才会帮我们去查。
所以让他们算是各有优缺点。
而我们用哪一种方法更好,则需要根据我们的具体情况去使用了