继承实现的三种策略
1.单表继承 table per class hierarchy,首选数据字典表
Sql,用type字段区分类型
CREATE TABLE `t_animal` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `type` VARCHAR(255) NOT NULL, `name` VARCHAR(255) NULL DEFAULT NULL, `age` INT(11) NULL DEFAULT NULL, `weight` VARCHAR(255) NULL DEFAULT NULL, `color` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`id`) )
discriminator需要紧接着在id后边
discrimination-value 此处定义子类的区分类型
<?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.lohamce.hibernate"> <class name="Animal" table="t_animal"> <id name="id"> <generator class="native" /> </id> <discriminator column="type" type="string" /> <property name="name" /> <property name="age" /> <subclass name="Cat" discriminator-value="C"> <property name="weight" /> </subclass> <subclass name="Bird" discriminator-value="B"> <property name="color" /> </subclass> </class> </hibernate-mapping>
//父类 public class Animal { private Integer id; private String name; private Integer age; } //子类1 public class Bird extends Animal{ private String color; } //子类2 public class Cat extends Animal { private String weight; } // 测试存储 @Test public void testSaveAnimals(){ Session session = null; Transaction tx = null; try{ session = HibernateUtil.openSession(); tx = session.beginTransaction(); Cat c = new Cat(); c.setAge(2); c.setName("Coffee"); c.setWeight("5kg"); Bird b = new Bird(); b.setAge(1); b.setName("Babe"); b.setColor("Yellow"); session.save(c); session.save(b); tx.commit(); } catch (Exception e){ e.printStackTrace(); tx.rollback(); } finally { HibernateUtil.close(session); } }
@Test public void testLoadAnimals(){ Session session = null; Transaction tx = null; try{ session = HibernateUtil.openSession(); tx = session.beginTransaction(); //load默认支持Lazy,所以并不支持多态的查询
//此处如果采用get()或者将Lazy设置为false,则支持多态查询 //Animal a = (Animal)session.load(Animal.class, 1); //System.out.println(a.getName()); Cat c = (Cat)session.load(Cat.class, 1); System.out.println(c.getName()); Bird b = (Bird)session.load(Bird.class, 2); System.out.println(b.getName()); tx.commit(); } catch (Exception e){ e.printStackTrace(); if(tx != null) tx.rollback(); } finally { HibernateUtil.close(session); } }
// Hql 查询支持多态 @SuppressWarnings("unchecked") @Test public void testQueryAnimals(){ Session session = null; Transaction tx = null; try{ session = HibernateUtil.openSession(); tx = session.beginTransaction(); Query query = session.createQuery("from Animal"); List<Animal> animals = (List<Animal>)query.list(); for( Animal a : animals){ if(a instanceof Bird) { System.out.println(((Bird)a).getColor()); }else if ( a instanceof Cat){ System.out.println(((Cat)a).getWeight()); } } tx.commit(); } catch (Exception e){ e.printStackTrace(); if(tx != null) tx.rollback(); } finally { HibernateUtil.close(session); } }
2.具体表继承 table per subclass,使用不多
CREATE TABLE `t_people` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `t_chinese` ( `cId` INT(11) NOT NULL, `freedom` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`cId`), INDEX `FKE80E0C22E3132291` (`cId`), CONSTRAINT `FKE80E0C22E3132291` FOREIGN KEY (`cId`) REFERENCES `t_people` (`id`) ); CREATE TABLE `t_japanese` ( `jId` INT(11) NOT NULL, `hardworking` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`jId`), INDEX `FK89CEB31CE3133CD8` (`jId`), CONSTRAINT `FK89CEB31CE3133CD8` FOREIGN KEY (`jId`) REFERENCES `t_people` (`id`) );
domain没有变化,只是需要修改xml.标签采用 join-subclass
<?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.lohamce.hibernate"> <class name="People" table="t_people"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <joined-subclass name="Chinese" table="t_chinese"> <key column="cId"></key> <property name="freedom"></property> </joined-subclass> <joined-subclass name="Japanese" table="t_japanese"> <key column="jId"></key> <property name="hardworking"></property> </joined-subclass> </class> </hibernate-mapping>
3.类表继承 table per concrete class
CREATE TABLE `t_chinese` ( `id` INT(11) NOT NULL, `name` VARCHAR(255) NULL DEFAULT NULL, `freedom` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `t_japanese` ( `id` INT(11) NOT NULL, `name` VARCHAR(255) NULL DEFAULT NULL, `hardworking` VARCHAR(255) NULL DEFAULT NULL, PRIMARY KEY (`id`) );
注意,此处的主键生成策略不能为自增,因为有很重要的一点,就是Hibernate在加载Session的时候,一个实体对应的id必须唯一
<?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.lohamce.hibernate"> <class name="People" abstract="true"> <id name="id"> <generator class="assigned" /> </id> <property name="name" /> <union-subclass name="Chinese" table="t_chinese"> <property name="freedom"></property> </union-subclass> <union-subclass name="Japanese" table="t_japanese"> <property name="hardworking"></property> </union-subclass> </class> </hibernate-mapping>