对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念。hibernate的集成映射可以理解为持久化类之间的继承关系。
Hibernate继承映射的三种策略:
1.基类一张表(父类、子类都在一张表中)
Animal基类:
package com.tao.entity; /** * 动物基类 * @author TaoGG * */ public class Animal { private int id; private String name; private String sex; 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; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "Animal [id=" + id + ", name=" + name + ", sex=" + sex + "]"; } }
Pig子类:
package com.tao.entity; public class Pig extends Animal{ private int weight; public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } @Override public String toString() { return "Pig [weight=" + weight + "]"; } }
Brid子类:
package com.tao.entity; public class Brid extends Animal{ private int height; public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } @Override public String toString() { return "Brid [height=" + height + "]"; } }
Animal.hbm.xml 配置文件:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.tao.entity"> <class name="Animal" table="t_animal"> <id name="id" column="animal_id"> <generator class="native" /> </id> <discriminator column="type" type="string"></discriminator> <property name="name" column="animal_name" length="100" /> <property name="sex" column="animal_sex" length="10" /> <subclass name="Pig" discriminator-value="Pig"> <property name="weight"></property> </subclass> <subclass name="Brid" discriminator-value="Brid"> <property name="height"></property> </subclass> </class> </hibernate-mapping>
在核心文件中引入,进行测试:
Test:
@org.junit.Test public void testSaveAnimal() throws Exception { Pig pig = new Pig(); pig.setName("小猪佩奇"); pig.setSex("MM"); pig.setWeight(20); Brid brid = new Brid(); brid.setName("小小鸟"); brid.setSex("GG"); brid.setHeight(10); session.save(pig); session.save(brid); } @org.junit.Test public void testGetAnimal() throws Exception { Query query = session.createQuery("from Animal"); List<Animal> list = query.list(); for(Animal animal:list){ if(animal instanceof Pig){ Pig p = (Pig) animal; System.out.println(p.getName()+"-"+p.getSex()+"-"+p.getWeight()); }else{ Brid b = (Brid) animal; System.out.println(b.getName()+"-"+b.getSex()+"-"+b.getHeight()); } } }
生成的数据库表结构:
输出:
Hibernate: select animal0_.animal_id as animal_i1_0_, animal0_.animal_name as animal_n3_0_, animal0_.animal_sex as animal_s4_0_, animal0_.weight as weight5_0_, animal0_.height as height6_0_, animal0_.type as type2_0_ from t_animal animal0_ 小猪佩奇-MM-20 小小鸟-GG-10
2.每个类对应一张表(父类一张表,一个子类一张表):
修改映射配置文件:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.tao.entity"> <class name="Animal"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <property name="sex" /> <joined-subclass name="Pig" table="t_pig"> <key column="pid"></key> <property name="weight"></property> </joined-subclass> <joined-subclass name="Brid" table="t_brid"> <key column="bid"></key> <property name="height"></property> </joined-subclass> </class> </hibernate-mapping>
运行Test 生成的数据库表结构:
animal表:
t_pig表:
t_brid表:
3.每个具体的类一张表(每个子类一张表)
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.tao.entity"> <class name="Animal" abstract="true"> <id name="id"> <generator class="uuid" /> </id> <property name="name" /> <property name="sex" /> <union-subclass name="Pig" table="t_pig"> <property name="weight"></property> </union-subclass> <union-subclass name="Brid" table="t_brid"> <property name="height"></property> </union-subclass> </class> </hibernate-mapping>
上面的表有个特点就是,t_pig和t_bird的主键永远都不会相同。因为表面上看起来这是两张表,但实际上存储的都是动物(同一类型),所以还可以看做是一张表。
在配置文件中 <union-subclass>标签中不需要key值了,注意Animal的主键生成策略不能是自增(native)了,如果自增的话,pig表中第一条记录id为1,bird表中第一条记录也为1,而它们在实际意义上属于同一类型(可以看做在一张表中),否则可能造成不同子类对应表中的主键相同,所以主键不可一致。
配置映射文件时,父类还用<class>标签来定义;用<union-subclass>标签定义两个子类,且每个类对应的表的信息是完全的,包含了所有从父类继承下来的属性。子类的特有属性同样用<property>定义即可。用abstract属性表示父类Animal为抽象类,这样Animal就不会映射成表了。