Hibernate延迟加载 lazy loading

2019-04-05 11:19栏目:编程程序

public static void main(String[] args) {
 
  DeptEntity dept = getDept("402882e762ae888d0162ae888e420000");

转载:

延迟加载在Hibernate中是默认延迟加载;

创建工程可以是java也可以是web

  //dept.getEmp()得到子表的记录集合
  System.out.println(dept.getEmp());

hibernate使用版本是:hibernate-release-4.3.4.Final

测试代码一:

1、引入jar文件

}

需要的jar包:hibernate-release-4.3.4Finallibrequired下所有jar包

HibernateTest.java

2、设计表同时开发和表的字段名一致的javabean(持久化类)

private static DeptEntity getDept(String did){
  Session session = sessionFactory.openSession();
  DeptEntity dept = (DeptEntity)session.get(DeptEntity.class, did);
  session.close();
  return dept;
}

ehcache  jar包:hibernate-release-4.3.4.Finalliboptionalehcache下所有包

代码:

3、创建对象-关系映射文件:映射文件的扩展名为 .hbm.xml 这里Login.hbm.xml文件

 

junit:junit-4.10.jar和mysql-connector-java-5.1.15-bin.jar

/**
 *
 */
package com.b510.examples;

<?xml version="1.0" encoding="UTF-8"?>

运行结果:

注:hibernate 4.2.5版本ehcache缓存不依赖commons-logging-1.1.1.jar,需要的是slf4j-api-1.6.1.jar

import java.util.Set;

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" ";

Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.javakc.hibernate.onetomany.entity.DeptEntity.emp, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
at org.hibernate.collection.internal.PersistentSet.toString(PersistentSet.java:326)
at java.lang.String.valueOf(String.java:2827)
at java.io.PrintStream.println(PrintStream.java:771)
at com.javakc.hibernate.onetomany.action.TestAction.main(TestAction.java:74)

项目结构如下
 
ca888会员登录 1  

import org.hibernate.Session;

<hibernate-mapping>

 

hibernate.cfg.xml

/**
 *
 * @author XHW
 *
 * @date 2011-7-18
 *
 */
public class HibernateTest {
 public static void main(String[] args) {
  new HibernateTest().update();
 }
 public void update(){
  Session session=HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();
  session.beginTransaction();
  Category category=(Category)session.get(Category.class, 1);
  System.out.println("id:" category.getId() "  ,name:" category.getName() ", description:" category.getDescription());
  
  Set<Product> products=category.getProducts();
  
  session.getTransaction().commit();  
 }
 
 
}

<class name="com.hw.entity.Student" table="tab_student">

集合延迟加载初始化失败,不能初始化一个代理。就是集合在非一对一对象关系中,为了节省资源是默认延迟加载,而get方法又是非延迟加载,所以在执行完一次数据库查询后就执行session.close();关闭了session,而集合是延迟加载,在使用集合时再加载,此时session已经关闭,所以得不到代理。解决方法:可以在主表的hbm配置文件中,在<set>标签里设置lazy="false",集合就不延迟加载了,因此在执行get方法时,集合也获取到了,就不会出现延迟加载问题了。

  1. <?xml version='1.0' encoding='utf-8'?>  
  2. <!DOCTYPE hibernate-configuration PUBLIC  
  3.         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
  4.         ";  
  5. <hibernate-configuration>  
  6.     <session-factory>  
  7.         <!-- Database connection settings -->  
  8.         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>  
  9.         <property name="connection.url">jdbc:mysql://127.0.0.1:3306/hibernate4</property>  
  10.         <property name="connection.username">root</property>  
  11.         <property name="connection.password">root</property>  
  12.         <!-- JDBC connection pool (use the built-in) -->  
  13.         <property name="connection.pool_size">1</property>  
  14.         <!-- SQL dialect -->  
  15.         <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>  
  16.         <!-- Enable Hibernate's automatic session context management -->  
  17.         <property name="current_session_context_class">thread</property>  
  18.         <!-- Disable the second-level cache -->  
  19.         <!--<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> 
  20.         -->  
  21.         <!-- 配置二级缓存 -->  
  22.         <property name="hibernate.cache.use_second_level_cache">true</property>  
  23.         <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>  
  24.         <!-- hibernate3的二级缓存配置 -->  
  25.         <!-- <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> -->  
  26.         <!-- 开启查询缓存 -->  
  27.         <property name="hibernate.cache.use_query_cache">true</property>  
  28.           
  29.         <!-- Echo all executed SQL to stdout -->  
  30.         <property name="show_sql">true</property>  
  31.         <!-- Drop and re-create the database schema on startup -->  
  32.         <property name="hbm2ddl.auto">update</property>  
  33.         <mapping class="com.test.pojo.User" />  
  34.     </session-factory>  
  35. </hibernate-configuration>  

运行结果:

<id name="id" type="integer" column="id"><!-- 如果列名和name名一致可以省去 -->

 

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate:
    select
        category0_.id as id1_0_,
        category0_.name as name1_0_,
        category0_.description as descript3_1_0_
    from
        users.category category0_
    where
        category0_.id=?
id:1  ,name:java, description:java好啊

时间类型 把 java.util.Date 改成 java.sql.Date

注意:hibernate4和hibernate3配置不一样,hibernate4是

这里我们看到我们关心的是id,name和description属性,

<generator class="native"></generator><!-- 主键自增 --></id>

  1. <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>  

虽然有:  Set<Product> products=category.getProducts(); 代码,即:不处理集合对象。但是我们只要的是:

<property name="name" type="string"></property>

 

  System.out.println("id:" category.getId() "  ,name:" category.getName() ", description:" category.getDescription());
输出的是id,name和description属性值,其他的我们不管,所以Hibernate用了lazy loading(延迟加载),带来的好处就是我们不关心的

<property name="score" type="float"></property>

而hibernate3的配置是

数据,不用现在加载,当我们要用的时候,才去加载

</class></hibernate-mapping>

  1. <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>  

测试代码二:

4、创建 Hibernate 配置文件(hibernate.cfg.xml)

 此处有一个疑问是:hibernate4的官方文档中,已经把class改了,但是属性名称没有改,还是 hibernate.cache.provider_class,不是上面的 hibernate.cache.region.factory_class,但是写成hibernate.cache.provider_class会 报下面错误

HibernateTest.java

<?xml version='1.0' encoding='UTF-8'?>

 

代码:

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" ";

Java代码 

/**
 *
 */
package com.b510.examples;

<!-- Generated by MyEclipse Hibernate Tools.                -->

  1. org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.spi.CacheImplementor]  
  2.     at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:186)  
  3.     at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:150)  
  4.     at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:131)  
  5.     at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:264)  
  6.     at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1790)  
  7.     at com.test.pojo.UserTest.beforeClass(UserTest.java:28)  
  8.     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
  9.     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  
  10.     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
  11.     at java.lang.reflect.Method.invoke(Method.java:597)  
  12.     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)  
  13.     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)  
  14.     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)  
  15.     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)  
  16.     at org.junit.runners.ParentRunner.run(ParentRunner.java:300)  
  17.     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)  
  18.     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)  
  19.     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)  
  20.     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)  
  21.     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)  
  22.     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)  
  23. Caused by: org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given, please either disable second level cache or set correct region factory class name to property hibernate.cache.region.factory_class (and make sure the second level cache provider, hibernate-infinispan, for example, is available in the classpath).  
  24.     at org.hibernate.cache.internal.NoCachingRegionFactory.buildTimestampsRegion(NoCachingRegionFactory.java:87)  
  25.     at org.hibernate.cache.spi.UpdateTimestampsCache.<init>(UpdateTimestampsCache.java:62)  
  26.     at org.hibernate.internal.CacheImpl.<init>(CacheImpl.java:72)  
  27.     at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:40)  
  28.     at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:35)  
  29.     at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.initiateService(SessionFactoryServiceRegistryImpl.java:91)  
  30.     at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:176)  
  31.     ... 20 more  

import java.util.Set;

<hibernate-configuration>

 说是hibernate.cache.region.factory_class属性没有配置,估计官方文档里没有把属性改过来。。。

import org.hibernate.Session;

<session-factory>

 

/**
 *
 * @author XHW
 *
 * @date 2011-7-18
 *
 */
public class HibernateTest {
 public static void main(String[] args) {
  new HibernateTest().update();
 }
 public void update(){
  Session session=HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();
  session.beginTransaction();
  Category category=(Category)session.get(Category.class, 1);
  System.out.println("id:" category.getId() "  ,name:" category.getName() ", description:" category.getDescription());
  
  Set<Product> products=category.getProducts();
  for(Product product:products){
   System.out.println("ID:  " product.getId() "  name:" product.getName() " price: " product.getPrice());
  }  
  session.getTransaction().commit();  
 }
 
 
}

<!-- hibernate 的mysql方言 -->

ehcache.xml

运行效果:

<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <ehcache xmlns:xsi=""  
  3.     xsi:noNamespaceSchemaLocation=""  
  4.     updateCheck="false">  
  5.     <!--  
  6.         name:cache唯一标识   
  7.         eternal:缓存是否永久有效   
  8.         maxElementsInMemory:内存中最大缓存对象数  
  9.         overflowToDisk(true,false):缓存对象达到最大数后,将缓存写到硬盘中  
  10.         diskPersistent:硬盘持久化  
  11.         timeToIdleSeconds:缓存清除时间   
  12.         timeToLiveSeconds:缓存存活时间  
  13.         memoryStoreEvictionPolicy:缓存清空策略  
  14.         1.FIFO:first in first out 先讲先出  
  15.         2.LFU: Less Frequently Used 一直以来最少被使用的  
  16.         3.LRU:Least Recently Used  最近最少使用的  
  17.     -->  
  18.     <defaultCache maxElementsInMemory="1000" eternal="false"  
  19.         timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />  
  20.     <cache name="userCache" eternal="false" maxElementsInMemory="1000"  
  21.         overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="3600"  
  22.         timeToLiveSeconds="3600" memoryStoreEvictionPolicy="LFU" />  
  23. </ehcache>  

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate:
    select
        category0_.id as id1_0_,
        category0_.name as name1_0_,
        category0_.description as descript3_1_0_
    from
        users.category category0_
    where
        category0_.id=?
id:1  ,name:java, description:java好啊
Hibernate: 
    select
        products0_.category_id as category2_1_,
        products0_.id as id1_,
        products0_.id as id0_0_,
        products0_.category_id as category2_0_0_,
        products0_.name as name0_0_,
        products0_.price as price0_0_,
        products0_.descripton as descripton0_0_
    from
        users.product products0_

<property name="connection.url">jdbc:mysql://localhost:3306/stu?useUnicode=true&characterEncoding=utf8</property>

 

    where
        products0_.category_id=?
ID:  1  name:java SE应用程序设计 price: 78.00
这里可以明确的告诉我们,当我们要加载Set集合的时候,这时候才去加载,而上面的例子,说明的是我们不加载的时候

<property name="connection.username">root</property>

User实体类

Hibernate就延迟加载

<property name="connection.password">root</property>

  1. package com.test.pojo;  
  2.   
  3. import javax.persistence.Entity;  
  4. import javax.persistence.GeneratedValue;  
  5. import javax.persistence.GenerationType;  
  6. import javax.persistence.Id;  
  7.   
  8. import org.hibernate.annotations.Cache;  
  9. import org.hibernate.annotations.CacheConcurrencyStrategy;  
  10.   
  11. @Entity  
  12. @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)  
  13. public class User {  
  14.     @Id  
  15.     @GeneratedValue(strategy=GenerationType.IDENTITY)  
  16.     private int id;  
  17.     private String name;  
  18.     private int age;  
  19.     public int getId() {  
  20.         return id;  
  21.     }  
  22.     public void setId(int id) {  
  23.         this.id = id;  
  24.     }  
  25.     public String getName() {  
  26.         return name;  
  27.     }  
  28.     public void setName(String name) {  
  29.         this.name = name;  
  30.     }  
  31.     public int getAge() {  
  32.         return age;  
  33.     }  
  34.     public void setAge(int age) {  
  35.         this.age = age;  
  36.     }  
  37.       
  38. }  

取消延迟加载:

<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

 

Category.hbm.xml

<!-- hibernate自动生成表 -->

UserTest测试类:

代码:

<property name="hibernate.hbm2ddl.auto">update</property>

  1. package com.test.pojo;  
  2. import org.hibernate.HibernateException;  
  3. import org.hibernate.Session;  
  4. import org.hibernate.SessionFactory;  
  5. import org.hibernate.cfg.Configuration;  
  6. import org.hibernate.service.ServiceRegistry;  
  7. import org.hibernate.service.ServiceRegistryBuilder;  
  8. import org.junit.BeforeClass;  
  9. import org.junit.Test;  
  10.   
  11. public class UserTest {  
  12.       
  13.     private static SessionFactory sessionFactory = null;  
  14.     @BeforeClass  
  15.     public static void beforeClass() {  
  16.         Configuration configuration = new Configuration();  
  17.           
  18.   
  19.         try {  
  20.             configuration.configure();  
  21.         } catch (HibernateException e) {  
  22.             // TODO Auto-generated catch block  
  23.             e.printStackTrace();  
  24.         }  
  25.               
  26.           
  27.         ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();  
  28.         sessionFactory = configuration.buildSessionFactory(serviceRegistry);  
  29.     }   
  30.     @Test  
  31.     public void testEhcache() {  
  32.         Session session = sessionFactory.openSession();  
  33.         session.beginTransaction();  
  34.         User u1 = (User) session.load(User.class, 3);  
  35.         System.out.println(u1.getName());  
  36.         session.getTransaction().commit();  
  37.         session.close();  
  38.         Session session2 = sessionFactory.openSession();  
  39.           
  40.         session2.beginTransaction();  
  41.         User u2 = (User) session2.load(User.class, 3);  
  42.         System.out.println(u2.getName());  
  43.         session2.getTransaction().commit();  
  44.         session2.close();  
  45.     }  
  46. }  

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.b510.examples.Category" table="category" catalog="users">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="increment" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="name" length="500" />
        </property>
        <property name="description" type="java.lang.String">
            <column name="description" length="500" />
        </property>
        <set name="products" inverse="true" lazy="false">
            <key>
                <column name="category_id" />
            </key>
            <one-to-many class="com.b510.examples.Product" />
        </set>
    </class>
</hibernate-mapping>

<!-- hibernate显示sql -->(运行底下会显示语句,可以删)

 结果:

测试代码:

<property name="show_sql">true</property>

 

HIbernateTest.java

<!-- hibernate 格式化sql-->(运行底下会显示语句,可以删)

  1. Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from User user0_ where user0_.id=?  
  2. zhangsan  
  3. zhangsan  

代码:

<property name="format_sql">true</property>

 

/**
 *
 */
package com.b510.examples;

<!-- hibernate映射文件 -->(点source的另一个 add加进去)

list二级缓存测试

import java.util.Set;

<mapping resource="com/hw/entity/Student.hbm.xml" />

  1. package com.test.pojo;  
  2. import java.util.List;  
  3.   
  4. import org.hibernate.HibernateException;  
  5. import org.hibernate.Session;  
  6. import org.hibernate.SessionFactory;  
  7. import org.hibernate.cfg.Configuration;  
  8. import org.hibernate.service.ServiceRegistry;  
  9. import org.hibernate.service.ServiceRegistryBuilder;  
  10. import org.junit.BeforeClass;  
  11. import org.junit.Test;  
  12.   
  13. public class UserTest {  
  14.       
  15.     private static SessionFactory sessionFactory = null;  
  16.     @BeforeClass  
  17.     public static void beforeClass() {  
  18.         Configuration configuration = new Configuration();  
  19.           
  20.   
  21.         try {  
  22.             configuration.configure();  
  23.         } catch (HibernateException e) {  
  24.             // TODO Auto-generated catch block  
  25.             e.printStackTrace();  
  26.         }  
  27.               
  28.           
  29.         ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();  
  30.         sessionFactory = configuration.buildSessionFactory(serviceRegistry);  
  31.     }   
  32.     @SuppressWarnings("unchecked")  
  33.     @Test  
  34.     public void testListEhcache() {  
  35.         Session session = sessionFactory.openSession();  
  36.         session.beginTransaction();  
  37.         List<User> users1 = (List<User>)session.createQuery("from User").setCacheable(true).list();  
  38.         for(User user : users1) {  
  39.             System.out.println(user.getName());  
  40.         }  
  41.         session.getTransaction().commit();  
  42.         session.close();  
  43.           
  44.         Session session2 = sessionFactory.openSession();  
  45.         session2.beginTransaction();  
  46.         List<User> users2 = (List<User>)session2.createQuery("from User").setCacheable(true).list();  
  47.         for(User user : users2) {  
  48.             System.out.println(user.getName());  
  49.         }  
  50.         session2.getTransaction().commit();  
  51.         session2.close();  
  52.     }  
  53. }  

import org.hibernate.Session;

</session-factory>

 输出结果:

/**
 *
 * @author XHW
 *
 * @date 2011-7-18
 *
 */
public class HibernateTest {
 public static void main(String[] args) {
  new HibernateTest().update();
 }
 public void update(){
  Session session=HibernateSessionFactoryUtil.getSessionFactory().getCurrentSession();
  session.beginTransaction();
  Category category=(Category)session.get(Category.class, 1);
  System.out.println("id:" category.getId() "  ,name:" category.getName() ", description:" category.getDescription());
  
  Set<Product> products=category.getProducts();
   
  session.getTransaction().commit();  
 }
 
 
}

</hibernate-configuration>

  1. Hibernate: select user0_.id as id1_0_, user0_.age as age2_0_, user0_ca888会员登录,.name as name3_0_ from User user0_  
  2. zhangsan  
  3. zhangsan  
  4. lisi  
  5. wangwu  
  6. zhangsan  
  7. zhangsan  
  8. lisi  
  9. wangwu  

运行效果:

5、加载xml文件,创建sessionFactory

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.
Hibernate:
    select
        category0_.id as id1_0_,
        category0_.name as name1_0_,
        category0_.description as descript3_1_0_
    from
        users.category category0_
    where
        category0_.id=?
Hibernate:
    select
        products0_.category_id as category2_1_,
        products0_.id as id1_,
        products0_.id as id0_0_,
        products0_.category_id as category2_0_0_,
        products0_.name as name0_0_,
        products0_.price as price0_0_,
        products0_.descripton as descripton0_0_
    from
        users.product products0_
    where
        products0_.category_id=?
id:1  ,name:java, description:java好啊
和测试代码一的运行结果相互比较,我们会发现,这次运行结果用了两条select语句。但是我们会发现

public class HibernateUtil {

第二条select语句,对于我们的需求是没有必要的,他只有一个用处就是占用我们的程序执行时间。当然,

public static Session getSession() {//获取当前session

这是我们不希望看到的结果。

return new Configuration().configure().buildSessionFactory().openSession()

一般情况下,Hibernate会默认给我们设置延迟加载。lazy="true" ,这样会提升我们的系统性能,所以一般情况下,我们不会去

}

设置lazy="false",当然在特殊的情况下,我们必须要取消延迟加载的时候,我们就把lazy="false",就可以了

}

6、开发crud

private Session session=null;

版权声明:本文由ca888发布于编程程序,转载请注明出处:Hibernate延迟加载 lazy loading