Hibernate学习笔记6
学习课程:
继承映射——单表映射(table per class hiberarchy) |
Hibernate_12_Extends_1 |
继承映射——具体表映射(table per subclass) |
Hibernate_13_Extends_2 |
继承映射——类表继承(table per concrete class) |
Hibernate_14_Extends_3 |
学习内容:
继承映射
对象模型图:

1.每棵继承树映射成一张表
t_animal
id |
name |
sex |
weight |
height |
type |
1 |
猪猪 |
true |
100 |
|
P |
2 |
鸟鸟 |
false |
|
50 |
B |
映射文件Animal.hbm.xml配置:
- <class name="Animal" table="t_animal" lazy="true">
- <id name="id" >
- <generator class="native" />
- </id>
- <discriminator column="type" type="string"/>
- <property name="name" />
- <property name="sex" />
- <subclass name="Pig" discriminator-value="P">
- <property name="weight" />
- </subclass>
- <subclass name="Bird" discriminator-value="B">
- <property name="height" />
- </subclass>
- </class>
|
|
2.每个子类映射成一张表
t_animal
id |
name |
sex |
1 |
猪猪 |
true |
2 |
鸟鸟 |
false |
t_pig
t_bird
映射文件Animal.hbm.xml配置:
- <joined-subclass name="Pig" table="t_pig">
- <key column="pig_id" />
- <property name="weight" />
- </joined-subclass>
- <joined-subclass name="Bird" table="t_bird">
- <key column="bird_id" />
- <property name="height" />
- </joined-subclass>
|
|
3.每个具体类映射成一张表
t_pig
id |
name |
sex |
weight |
1 |
猪猪 |
true |
100 |
t_bird
id |
name |
sex |
height |
2 |
鸟鸟 |
false |
50 |
映射文件Animal.hbm.xml配置:
- <class name="Animal" table="t_animal" lazy="true">
- <id name="id" >
- <generator class="uuid" />
- </id>
- <property name="name" />
- <property name="sex" />
- <union-subclass name="Pig" table="t_pig">
- <property name="weight" />
- </union-subclass>
- <union-subclass name="Bird" table="t_bird">
- <property name="height" />
- </union-subclass>
- </class>
d |
|
进行测试的方法
testSave1()
插入两条记录
测试结果:插入成功
1 P 八戒 1 888
NULL
2 B 凤凰 0 NULL 999 |
|
- Pig pig = new Pig();
- pig.setName("八戒");
- pig.setSex(true);
- pig.setWeight(888);
- session.save(pig);
- Bird bird = new Bird();
- bird.setName("凤凰");
- bird.setSex(false);
- bird.setHeight(999);
- session.save(bird);
|
testSave2()
插入两条记录
测试结果:插入成功
1 P 八戒 1 888
NULL
2 B 凤凰 0 NULL 999
注:此测试方法用于第三种映射方式:每个具体类映射成一张表
中插入数据的两种情况
1.将id的生成策略给为assigned,
2.修改id的类型为Strng,生成策略为uuid |
|
- Pig pig = new Pig();
- pig.setName("八戒");
- pig.setSex(true);
- pig.setWeight(888);
- session.save(pig);
- Bird bird = new Bird();
- bird.setName("凤凰");
- bird.setSex(false);
- bird.setHeight(999);
- session.save(bird);
|
testLoad1()
加载方式load
方向:通过Pig加载,查询Pig的name字段值
测试结果:
pig's name :八戒
pig's weight :888 |
|
- Pig pig = (Pig) session.load(Pig.class, 1);
- System.out.println("pig's name :" + pig.getName());
- System.out.println("pig's weight :" + pig.getWeight());
|
testLoad2()
加载方式load
方向:通过Animal加载,查询Animal的name字段值
测试结果:
animal's name :八戒 |
|
- Animal animal = (Animal)
- session.load(Animal.class, 1);
- System.out.println("animal's name :" + animal.getName());
|
testLoad3()
加载方式load 方向:通过Animal加载,判断 (animal instanceof Pig )Animal中是不是Pig
测试结果:
no ,this is not a pig |
|
- Animal animal = (Animal) session.load(Animal.class, 1);
- if (animal instanceof Pig) {
- System.out.println("yes , this is a pig !");
- } else {
- System.out.println("no ,this is not a pig ");
- }
|
testLoad4()
通过Get进行查询,Animal返回具体的Pig类型,(animal instanceof Pig)为true
测试结果:
yes , this is a pig ! |
|
- Animal animal = (Animal) session.get(Animal.class, 1);
- if (animal instanceof Pig) {
- System.out.println("yes , this is a pig !");
- } else {
- System.out.println("no ,this is not a pig ");
- }
|
testLoad5()
查询方式为load ,设置 <class lazy="false">,支持多台查询,
查询Animal返回具体的Pig类型,(animal instanceof Pig)为true
测试结果:
no ,this is not a pig |
|
- Animal animal = (Animal) session.load(Animal.class, 1);
- if (animal instanceof Pig) {
- System.out.println("yes , this is a pig !");
- } else {
- System.out.println("no ,this is not a pig ");
- }
|
testLoad6()
现将lazy设置为true 通过HQL进行查询
List animalList = session.createQuery( "from Animal" ).list();
HQL支持多态查询,能够正确的鉴别出真正的类型
测试结果:
这是一头猪。
这是一只鸟。 |
|
- List<Animal> animalList =
- session.createQuery( "from Animal" ).list();
- for ( Animal a : animalList ){
- if ( a instanceof Pig){
- System.out.println( "这是一头猪。" );
- } else if ( a instanceof Bird ){
- System.out.println( "这是一只鸟。" );
- } else {
- System.out.println( "这是一个新品种????????" );
- }
- }
|
testLoad7()
通过HQL进行查询
查询类型为Object
测试结果:
这是一头猪。
这是一只鸟。 |
|
- List<Animal> animalList =
- session.createQuery( "from java.lang.Object" ).list();
- for ( Animal a : animalList ){
- if ( a instanceof Pig){
- System.out.println( "这是一头猪。" );
- } else if ( a instanceof Bird ){
- System.out.println( "这是一只鸟。" );
- } else {
- System.out.println( "这是一个新品种????????" );
- }
- }
|
补充信息
1、理解如何映射
因为类继承树肯定是对应多个类,要把多个类的信息存放在一张表中,必须有
某种机制来区分哪些记录是属于哪个类的。这种机制就是,在表中添加一个字段,用这
个字段的值来进行区分。用hibernate实现这种策略的时候,有如下步骤:
父类用普通的<class>标签定义
在父类中定义一个discriminator,即指定这个区分的字段的名称和类型
如:<discriminator column=”XXX” type=”string”/>
子类使用<subclass>标签定义,在定义subclass的时候,需要注意如下几点:
Subclass标签的name属性是子类的全路径名
在Subclass标签中,用discriminator-value属性来标明本子类的discriminator字段(用来区分不同类的字段)
的值Subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标
签平行。 当subclass标签的定义与class标签平行的时候,需要在subclass标签中,添加extends属性,里面的值
是父类的全路径名称。子类的其它属性,像普通类一样,定义在subclass标签的内部。
2、理解如何存储
存储的时候hibernate会自动将鉴别字段值插入到数据库中,在加载数据的时候,hibernate能根据这个鉴别值
正确的加载对象