zoukankan      html  css  js  c++  java
  • Hibernate检索策略之5.2多对一单向关联检索策略——Hibernate4究竟怎么玩

    今天开始多对一单向关联检索策略。

    先看一下多端域模型:

     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 = false)
    24 //默认是false,是否延迟加载类级别实例
    25 @Entity
    26 @Table(name = "t_studentum")
    27 public class StudentUM extends BaseDomain {
    28 
    29     private static final long serialVersionUID = 1L;
    30 
    31     private Integer id;
    32 
    33     private String name;
    34 
    35     private ClassUO classUO;
    36 
    37     @Id
    38     @GeneratedValue(strategy = GenerationType.AUTO)
    39     public Integer getId() {
    40         return id;
    41     }
    42 
    43     public void setId(Integer id) {
    44         this.id = id;
    45     }
    46 
    47     public String getName() {
    48         return name;
    49     }
    50 
    51     public void setName(String name) {
    52         this.name = name;
    53     }
    54 
    55     @ManyToOne(fetch = FetchType.EAGER)
    56     @JoinColumn(name = "classid", nullable = false)
    57     @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    58     public ClassUO getClassUO() {
    59         return classUO;
    60     }
    61 
    62     public void setClassUO(ClassUO classUO) {
    63         this.classUO = classUO;
    64     }
    65 
    66     public StudentUM() {
    67         super();
    68     }
    69 
    70     public StudentUM(String name, ClassUO classUO) {
    71         super();
    72         this.name = name;
    73         this.classUO = classUO;
    74     }
    75 
    76 }

    接下来是一端域模型:

    ClassUO
     1 package com.bao.sample.retrieve.strategy.umto;
     2 
     3 import javax.persistence.GeneratedValue;
     4 import javax.persistence.GenerationType;
     5 import javax.persistence.Id;
     6 import javax.persistence.Table;
     7 
     8 import javax.persistence.Entity;
     9 
    10 import com.bao.sample.base.domain.BaseDomain;
    11 
    12 /**
    13  * 
    14  * @Description 多对一单向关联--单向关联一端
    15  * @author Bob hehe198504@126.com
    16  * @date 2012-8-27
    17  */
    18 @Entity
    19 @Table(name = "t_classuo")
    20 public class ClassUO extends BaseDomain {
    21 
    22     private static final long serialVersionUID = 1L;
    23 
    24     private Integer id;
    25     private String name;
    26 
    27     @Id
    28     @GeneratedValue(strategy = GenerationType.AUTO)
    29     public Integer getId() {
    30         return id;
    31     }
    32 
    33     public void setId(Integer id) {
    34         this.id = id;
    35     }
    36 
    37     public String getName() {
    38         return name;
    39     }
    40 
    41     public void setName(String name) {
    42         this.name = name;
    43     }
    44 
    45     public ClassUO() {
    46         super();
    47     }
    48 
    49     public ClassUO(String name) {
    50         super();
    51         this.name = name;
    52 
    53     }
    54 
    55 }

    再看一下PO基类,基类通过反射实现了equals(),hasCode()和toString()三个方法,继承该基类的域模型就可以不需要再去实现了。

    BaseDomain
     1 package com.bao.sample.base.domain;
     2 
     3 import java.io.Serializable;
     4 
     5 import org.apache.commons.lang3.builder.EqualsBuilder;
     6 import org.apache.commons.lang3.builder.HashCodeBuilder;
     7 import org.apache.commons.lang3.builder.ToStringBuilder;
     8 
     9 /**
    10  * @Description PO基类实现Serializable接口,以便JVM可以序列化PO实例.利用反射实现了equals(),hasCode()和toString()方法
    11  * @author Bob hehe198504@126.com
    12  * @date 2012-7-25
    13  */
    14 public class BaseDomain implements Serializable {
    15 
    16     private static final long serialVersionUID = 1L;
    17 
    18     public boolean equals(Object obj) {
    19         return EqualsBuilder.reflectionEquals(this, obj);
    20     }
    21 
    22     public int hasCode() {
    23         return HashCodeBuilder.reflectionHashCode(this);
    24     }
    25 
    26     public String toString() {
    27         return ToStringBuilder.reflectionToString(this);
    28     }
    29 }

     在讲解检索策略之前呢,先说一下@Entity和@Table注解,前者是标识该类为域模型,在applicationContext.xml中进行如下配置后,程序便会扫描该包下及其子包下的类注解,不同的注解表示不同的组件。

    1 <context:component-scan base-package="com.bao.sample.retrieve.strategy.umto" />

    @Table与数据库表对应,其属性name的值即为该域模型对应数据表的名称。

    先讲@ManyToOne,看一下网上这张图片,延迟和获取选项的等效注解:

    在多对一中,@ManyToOne(fetch = FetchType.EAGER)即表示,多端立即加载、一端迫切连接。

    下面看一下测试的方法(数据表数据仍然是5.1节中的数据):

     1     /**
     2      * @Description @ManyToOne(fetch = FetchType.EAGER)时检索关联对象
     3      * 
     4      */
     5     @Test
     6     public void fetchStudentByEager() {
     7         StudentUMService studentUMService = (StudentUMService) applicationContext
     8                 .getBean("studentUMService");
     9         StudentUM studentUM = studentUMService.getById(1);
    10 
    11         ClassUO classUO = studentUM.getClassUO();
    12         System.out.println("迫切连接时关联对象类型:" + classUO.getClass());
    13 
    14         System.out.println(classUO.getId());//①
    15         System.out.println("------迫切的分割线------");
    16         System.out.println(classUO.getName());//②
    17 
    18     }

    控制台输出的信息:

     1 Hibernate: 
     2     select
     3         studentum0_.id as id10_1_,
     4         studentum0_.classid as classid10_1_,
     5         studentum0_.name as name10_1_,
     6         classuo1_.id as id9_0_,
     7         classuo1_.name as name9_0_ 
     8     from
     9         t_studentum studentum0_ 
    10     inner join
    11         t_classuo classuo1_ 
    12             on studentum0_.classid=classuo1_.id 
    13     where
    14         studentum0_.id=?
    15 迫切连接时关联对象类型:class com.bao.sample.retrieve.strategy.umto.ClassUO
    16 1
    17 ------迫切的分割线------
    18 class one

    由此可以看出,检索策略使用迫切连接,多端和一端对象都不是代理类的实例。

    当@ManyToOne(fetch = FetchType.EAGER)时,检索的sql语句使用left out join或者inner join方式,具体采用何种方式,根据@JoinColumn(name = "classid", nullable = false)中的nullable属性决定,当nullable=true(默认),会使用left outer join;当nullable=false,会使用inner join.

    可以对比一下延迟获取:

     1     /**
     2      * @Description @ManyToOne(fetch=FetchType.LAZY)时检索关联对象
     3      * 
     4      */
     5     @Test
     6     public void fetchStudentByLazy() {
     7         StudentUMService studentUMService = (StudentUMService) applicationContext
     8                 .getBean("studentUMService");
     9         StudentUM studentUM = studentUMService.getById(1);
    10 
    11         ClassUO classUO = studentUM.getClassUO();
    12         System.out.println(classUO.getId());
    13 
    14         System.out.println("------延迟的分割线------");
    15         System.out.println(classUO.getName());
    16     }

    控制台输出结果:

     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 ------延迟的分割线------

    并有错误提示:org.hibernate.LazyInitializationException: could not initialize proxy - no Session。
    已经熟悉了该错误了吧,session关闭了,再去查询时报错。

    在解释一下:

    当@ManyToOne(fetch=FetchType.LAZY),即从OrderUM导航CustomerUO采用延迟加载时,导航的CustomerUO为一个代理对象,只初始化CustomerUO的标识符,若此时再去调用CustomerUO其他属性时,hibernate会去数据库中进行真正的查询,而getCurrentSesion随事务的提交已经关闭,所以会报org.hibernate.LazyInitializationException: could not initialize proxy - no Session.不能初始化代理类的错误.

    今天就到这里。2012-08-30 00:10:23 听雨轩 

  • 相关阅读:
    按钮的样式
    UIButton的状态
    什么是按钮
    图标下载网站 http://www.easyicon.net/
    开发中常用的颜色
    iOS中播放音效
    imagenamed和imageWithContentOfFile的区别
    资源存放问题
    UIImageView的序列帧动画
    UIImageView的frame设置
  • 原文地址:https://www.cnblogs.com/geyifan/p/2662924.html
Copyright © 2011-2022 走看看