每个具体类对应一个表

  • 写一个虚拟父类,用具体类来继承这个虚拟父类,有多少个具体类就建多少张表,父表的外键关联全部的这些具体表
  • 由于根类是虚拟的,在父表这里也不必配置集合映射了,直接在具体类的映射文件中配置多对一的映射即可。
  • 通过外键来获取这些具体类时比较麻烦,要一个一个地去获取,然后再集成一个大集合
  • 下面举了一个例子,是学生拥有多张生活照和工作照的例子

     //学生父表
     public class Student {
    
         private long id;
         private String name;
         private Set<String> images;
    }
    
    //照片虚拟类
    public abstract class Image {
    
         private int id;
         private String imageName;
         private Student student;
     }
    
     //生活照和工作照分别为其子类
     public class LifeImage extends Image{}
     public class WorkImage extends Image{}
    
     //配置学生映射文件
     <class name="Student" table="t_student">
    
     <id name="id" column="stuId">
         <generator class="native"></generator>
     </id>
    
     <property name="name"></property>
    
     <!-- Image类是抽象类,主要是两个实现类在起作用,所以这里配置了Image的映射也没什么用 -->
    
     </class>
    
     //配置照片具体类映射文件(重点是都要加上下面这条)
     <many-to-one name="student" column="stuId" class="com.java1234.model.Student"></many-to-one>
    
    • 数据库

      //配置简单,但是获取复杂,假如有很多子类那么获取难度很大
      @Test
      public void testGetAllImages() {

      List<Image> imageList=new ArrayList<Image>();
      int stuId=1;
      //多态
      List<Image> lifeImageList=(List<Image>)session.createQuery("from LifeImage l where l.student.id="+stuId).list();
      imageList.addAll(lifeImageList);
      List<Image> workImageList=(List<Image>)session.createQuery("from WorkImage w where w.student.id="+stuId).list();
      imageList.addAll(workImageList);
      Iterator iterator=imageList.iterator();
      while(iterator.hasNext()) {
          Image image=(Image) iterator.next();
          System.out.println(image.getImageName());
      }
      

      }

      根类对应一个表

  • 创建一个图片的根类(非虚拟类),加上类型属性来区别具体类;
  • 让两个具体类来继承它,但是真正起作用的还是根类
  • 在学生配置文件中加入根类的集合映射
  • 在根类的映射文件中则要加入解释器和子类来区别图片具体类型
  • 获取的话直接一次获取根类即可

     //学生父表
     public class Student2 {
    
         private int id;
         private String name;
         private Set<Image2> images;
     }
    
     //照片类
     public class Image2 {
    
         private int id;
         private String imageName;
         private String imageType; //用来区别照片类型
         private Student2 student;
    }
    
     //生活照和工作照分别为其子类
     public class LifeImage2 extends Image2{}
     public class WorkImage2 extends Image2{}
    
    //学生映射文件
    <set name="images">
         <key column="stuId"></key>
         <one-to-many class="com.java1234.model.Image2"></one-to-many>
     </set>
    
     //照片映射文件
     <many-to-one name="student" column="stuId" class="com.java1234.model.Student2"></many-to-one>
    
     <!--解释器,主要是作为标识的-->
     <discriminator column="imageType" type="string"></discriminator> <!--默认是string-->
     <!--子类-->
     <subclass name="com.java1234.model.LifeImage2" discriminator-value="li"></subclass> <!--假如imageType是li这个值那就是LifeImage2类-->
     <subclass name="com.java1234.model.WorkImage2" discriminator-value="wi"></subclass>
    
    • 数据库

      //配置略复杂(要配置subclass),但获取简单,直接获取根类即可
      @Test
      public void testGetAllImages2() {

      Student2 student2=(Student2)session.get(Student2.class, 1); //int的话可以直接放数字
      Set<Image2> images=student2.getImages();
      Iterator iterator=images.iterator();
      while(iterator.hasNext()) {
          Image2 image2=(Image2)iterator.next();
          System.out.println(image2.getImageName());
      }
      

      }

      每个类对应一个表

  • 前两种要么只有根表,要么只有具体表,这种既有根表又有具体表。
  • 跟第二种一样,先创建具体的根类,再创建两个具体类继承根类
  • 学生映射文件中配置根类的集合映射,根类的映射文件中配置一个外键同时关联两张具体类的子表
  • 获取的时候统一获取

    //学生父表
    public class Student3 {
    
        private int id;
        private String name;
        private Set<Image3> images;
    }
    
    //根类
    public class Image3 {
    
        private int id;
        private String imageName;
        private Student3 student;
    }
    
    //具体类
    public class LifeImage3 extends Image3{}
    public class WorkImage3 extends Image3{}
    
    //学生映射文件
    <set name="images">
        <key column="stuId"></key>
        <one-to-many class="com.java1234.model.Image3"></one-to-many>
    </set>
    
    //根类映射文件
    <many-to-one name="student" column="stuId" class="com.java1234.model.Student3"></many-to-one>
    
    <!-- 创建两张关联表 -->
    <joined-subclass name="com.java1234.model.LifeImage3" table="t_lifeImage3">
        <key column="lifeImageId"></key> <!-- 主键,将会关联本表(总图片表)的主键,也即是三张图片表的主键同时都是外键 -->
    </joined-subclass>
    <joined-subclass name="com.java1234.model.WorkImage3" table="t_workImage3">
        <key column="workImageId"></key>
    </joined-subclass>
    
    • 数据库

    • 因为两张具体表的主键都跟根表的主键关联,因此两张具体表的主键不能相同,生活表有1的主键,工作表就不能出现1的主键

//直接获取即可
@Test
public void testGetAllImages3() {
    Student3 student3=(Student3)session.get(Student3.class, 1); //int的话可以直接放数字
    Set<Image3> images=student3.getImages();
    Iterator iterator=images.iterator();
    while(iterator.hasNext()) {
        Image3 image3=(Image3)iterator.next();
        System.out.println(image3.getImageName());
    }
}

代码实例

  • HibernateExtends