首页 > 技术文章 > (11)映射继承关系二之每个类对应一张表(@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

TestAndDevelp 2017-11-13 17:53 原文

这种策略支持双向的一对多关联,这里不支持IDENTITY生成器策略。因为存在多态查询,所以id在继承关系的表中必须是唯一的。这就意味着不能用AUTO和IDENTITY生成器。
在mysql中,只能用生成表id来使得多个表的id保持不同。因为父类中含有共同的属性,简单来讲id同,就在父表中,所以子表不用再写生成表了。在实体中,每个表都含有父类及子类特有的属性字段。
person类

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)//继承策略是每个类层次结构映射一张表
@TableGenerator(
name="t_gen",//(requested)A unique generator name that can be referenced by one or more classes to be the generator for id values.
table="t_gen_table",//Name of table that stores the generated id values.
pkColumnName = "t_key",//pk列名
valueColumnName = "t_value",//pk值列名
pkColumnValue="person_pk",//pk列值
initialValue=1,
allocationSize=1
/*
 * 在这种方式多态查询中,不能确定是哪个子类的,所以学生、教师的id不能相同。根据多态的测试结果,也能看出id不能相同,所以mysql不嫩用自动生成策略
 * 用一个id生成表,来确定插入时 的id是什么
 */

)
public class Person {

    private int id;
    private String name;

    @Id
    @GeneratedValue(generator="t_gen",strategy=GenerationType.TABLE)

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }


}

student 类继承person类

@Entity

public class student extends Person {


    private int score;

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }   
}

Test
在利用多态查询中,是将所有的表联合起来,组合成所有的类公用一张表的形式

@Test
    public void testSave() {
        student s=new student();
        s.setName("s1");
        s.setScore(80);

        teacher t=new teacher();
        t.setName("t1");
        t.setTitle("高级");

        Session session=sf.getCurrentSession();
        session.beginTransaction();
        session.save(s);
        session.save(t);
        session.getTransaction().commit();


    }

    @Test
    public void testGet() {
        testSave();

        Session session=sf.getCurrentSession();
        session.beginTransaction();
        //student s=(student) session.get(student.class, 1);
        /*
         * 指定学生表,则会输出学生表的信息
         select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.score as score2_0_ 
    from
        student student0_ 
    where
        student0_.id=?
         */

        //使用多态:
        Person p=(Person) session.get(Person.class, 2);
        /*
         *  
        select
        person0_.id as id0_0_,
        person0_.name as name0_0_,
        person0_.title as title1_0_,
        person0_.score as score2_0_,
        person0_.clazz_ as clazz_0_ 
    from
        ( select  id, null as title, name,null as score,   0 as clazz_ from Person 
          union
          select id, title,  name,null as score, 1 as clazz_  from   teacher 
          union 
          select id,  null as title, name, score,   2 as clazz_   from  student   
       ) person0_ 
where
    person0_.id=?
       union用于合并两个或者多个select语句的结果集,并消去重复行。
       union内部的select语句必须有相同数目的列,列也必须有相似的数据类型
           上面的大from语句相当于将子表数据合并成了single.type的形式。
           再根据id确定是哪个子类的。


         */
        session.getTransaction().commit();



    }

推荐阅读