首页 > 技术文章 > (12)映射继承关系三之连接的子类(@Inheritance(strategy=InheritanceType.JOINED))

TestAndDevelp 2017-11-13 18:30 原文

这种方式:父类存放子类和父类的公共字段, 父类和子类中存在一一对应的关系,子类的id参考父类的id


@Entity
@Inheritance(strategy=InheritanceType.JOINED)

public class Person {

    private int id;
    private String name;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

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
当给具体的子类时,因为person中有student字段,所以一定会进行表连接(先连接,后where)
当利用多态查询时,先进行所有表的连接,所以若select * 按照下面的连接,则会显示6条数据
id name id title id score
其中id name是person的 然后连接老师 得到 id name id title
然后再连接student 得到 6条记录。【而且连接都是用的父类和子类id的连接,必然连接成功,因为父类和子类是一一对应的。因为是左外连接,所以只要有父类,则就能连接上,比如有些id ,教师里面没有则用null补】
从上面连接得到的结果可以看出,重复列不会自动删除。
当id=1时
id name id title id score
1 s1 null null 1 80
毕竟要选出某个人具体信息,而且通过select*得到这么多重复数据。如何区分是哪个子类呢,从上面可以看出person里必有id
当不属于某个类时,其id为null,所以我们只要找谁的id 不为空,则说明是哪个类的。
case
when person0_1_.id is not null then 1 [列值,确定是学生、教师、人。给个编号]
when person0_2_.id is not null then 2
when person0_.id is not null then 0
end as clazz_0_ [列名 ]
case多中选一,则先从子类开始找,最后是父类

@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();
        /*
         * CREATE TABLE `student` (
          `score` int(11) NOT NULL,
          `id` int(11) NOT NULL,
           PRIMARY KEY  (`id`),
           KEY `FK8FFE823B415D44C3` (`id`),
           CONSTRAINT `FK8FFE823B415D44C3` FOREIGN KEY (`id`) REFERENCES `person` (`id`)
           ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


         */

    }

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

        Session session=sf.getCurrentSession();
        session.beginTransaction();
        //student s=(student) session.get(student.class, 1);
        /*
         * inner join:就是并不参考左边表或者右边表,select两表均有的数据
         *   select
        student0_.id as id0_0_,学生表查到
        student0_1_.name as name0_0_,//从用户表查到
        student0_.score as score2_0_ 学生表查到
    from
        student student0_ //这句话:将student表重命名为student0_
    inner join
        Person student0_1_ 
            on student0_.id=student0_1_.id 
    where
        student0_.id=?

         */
        Person p=(Person) session.get(Person.class, 2);
        /*
         * 因为不确定是哪个子类,所以通过id连接所有的子类,然后根据id获取某条信息
         select
        person0_.id as id0_0_,
        person0_.name as name0_0_,
        person0_1_.title as title1_0_,
        person0_2_.score as score2_0_,
        case
            when person0_1_.id is not null then 1  [列值,确定是学生、教师、人。给个编号]
            when person0_2_.id is not null then 2 
            when person0_.id is not null then 0 
        end as clazz_0_ [列名 ]
    from
        Person person0_ 
    left outer join等价于left join
        teacher person0_1_ 
            on person0_.id=person0_1_.id 
    left outer join
        student person0_2_ 
            on person0_.id=person0_2_.id 
    where
        person0_.id=1


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



    }

推荐阅读