• Hibernate检索策略之5.1类级别检索策略——Hibernate4究竟怎么玩


    今天开始Hibernate 4的检索策略。

    Hibernate的检索策略有立即检索、延迟检索和迫切左连接检索三种方式。

    检索策略 类级别 关联级别
    立即检索 立即加载指定的对象 立即加载与指定对象相关联的对象
    延迟检索 延迟加载指定的对象 延迟加载与指定对象相关联的对象
    迫切左外连接 不适用 通过左外连接加载与指定对象相关联的对象

    以上是三种检索策略分别在类级别和关联级别中的不同点的说明。下面以Student与Class类多对一单向关联,举例对类级别中的检索策略进行说明。项目采用分层的方式,接近实际的开发流程。(为了方便查看放在了同一包下)

    在类级别检索中只需要用到一端的实体类、service和dao层即可,在此以多端为例:

    以下图分别是包的结构和表结构及数据:

    其中dao层和service层只需继承基类即可,具体代码可参考(待补充)无需其他代码。

    StudentUM
     1 package com.bao.sample.retrieve.strategy.umto;
     2 
     3 import javax.persistence.Entity;
     4 import javax.persistence.FetchType;
     5 import javax.persistence.GeneratedValue;
     6 import javax.persistence.GenerationType;
     7 import javax.persistence.Id;
     8 import javax.persistence.JoinColumn;
     9 import javax.persistence.ManyToOne;
    10 import javax.persistence.Table;
    11 
    12 import org.hibernate.annotations.Cascade;
    13 import org.hibernate.annotations.Proxy;
    14 
    15 import com.bao.sample.base.domain.BaseDomain;
    16 
    17 /**
    18  * 
    19  * @Description 单向关联多端
    20  * @author Bob hehe198504@126.com
    21  * @date 2012-8-27
    22  */
    23 @Proxy(lazy = true)
    24 @Entity
    25 @Table(name = "t_studentum")
    26 public class StudentUM extends BaseDomain {
    27 
    28     private static final long serialVersionUID = 1L;
    29 
    30     private Integer id;
    31 
    32     private String name;
    33 
    34     private ClassUO classUO;
    35 
    36     @Id
    37     @GeneratedValue(strategy = GenerationType.AUTO)
    38     public Integer getId() {
    39         return id;
    40     }
    41 
    42     public void setId(Integer id) {
    43         this.id = id;
    44     }
    45 
    46     public String getName() {
    47         return name;
    48     }
    49 
    50     public void setName(String name) {
    51         this.name = name;
    52     }
    53 
    54     @ManyToOne(fetch = FetchType.LAZY)
    55     @JoinColumn(name = "classid", nullable = false)
    56     @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    57     public ClassUO getClassUO() {
    58         return classUO;
    59     }
    60 
    61     public void setClassUO(ClassUO classUO) {
    62         this.classUO = classUO;
    63     }
    64 
    65     public StudentUM() {
    66         super();
    67     }
    68 
    69     public StudentUM(String name, ClassUO classUO) {
    70         super();
    71         this.name = name;
    72         this.classUO = classUO;
    73     }
    74 
    75 }

    此处类注解使用@Proxy(lazy = true),表示延迟检索指定对象。从测试类中可以看到,第22行输出“延迟加载:1”,表示执行正常,而在第23行打印那么时却报错了:org.hibernate.LazyInitializationException: could not initialize proxy - no Session。这个异常很简单,由于是延迟加载,studentUM只是一个代理类的实例而已,这个实例只初始化了标识符属性,其他属性都是null,当调用其他属性时才会执行真正的查询语句,但此时session已经关闭,无法执行执行查询,所以才会报错no Session。

     1 package com.bao.sample.retrieve.strategy.umto;
     2 
     3 import org.junit.Test;
     4 import org.springframework.context.ApplicationContext;
     5 import org.unitils.UnitilsJUnit4;
     6 import org.unitils.spring.annotation.SpringApplicationContext;
     7 
     8 import com.bao.sample.retrieve.strategy.umto.StudentUM;
     9 import com.bao.sample.retrieve.strategy.umto.StudentUMService;
    10 
    11 public class StudentUMServiceTest extends UnitilsJUnit4 {
    12 
    13     @SpringApplicationContext( { "applicationContext.xml" })
    14     private ApplicationContext applicationContext;
    15 
    16     @Test
    17     public void loadStudent() {
    18         StudentUMService studentUMService = (StudentUMService) applicationContext
    19                 .getBean("studentUMService");
    20         StudentUM studentUM = studentUMService.loadById(1);
    21 
    22         System.out.println("延迟加载:" + studentUM.getId());
    23         System.out.println("报错:" + studentUM.getName());
    24 
    25     }
    26 
    27 }

    如果将该注解@Proxy(lazy = true)删除,或改为@Proxy(lazy = false),再次执行测试方法,便可以看到如下输出:

     1 Hibernate: 
     2     select
     3         studentum0_.id as id10_0_,
     4         studentum0_.classid as classid10_0_,
     5         studentum0_.name as name10_0_ 
     6     from
     7         t_studentum studentum0_ 
     8     where
     9         studentum0_.id=?
    10 延迟加载:1
    11 报错:jack

    先前报错的地方,已经有正确的信息“jack”输出了。在此之前也已经执行了查询语句。

    @Proxy仅对load()方法有效,false表示立即检索;默认为true,表示延迟检索.此时不会执行select语句,仅返回代理类的实例.
    以上就是在类上加Proxy注解对于session.load()方法的区别,而session.get()方法没有这个限制,get方法在类级别永远都是立即加载检索的,而load方法在类级别上默认是延迟加载的。

    2012-08-29 00:43:04 听雨轩

  • 相关阅读:
    Django 常用过滤器
    计算机概论(2)
    计算机概论(1)
    Django URL视图
    模板标签之if、for
    Django 渲染模板、路径配置、变量使用。

    字符串用法
    hashlib模块
    小列
  • 原文地址:https://www.cnblogs.com/geyifan/p/2661022.html
Copyright © 2020-2023  润新知