每个具体类一张表
我们看看这种配置需要怎么做?
Hibernate继承映射的第一种策略:每个具体类一张表 1、如何映射 这种策略是使用union-subclass标签来定义子类的。每个子类对应一张表,而且这个表的信息是完备的, 即包含了所有从父类继承下来的属性映射的字段(这就是它跟joined-subclass的不同之处,joined-subclass定义的子类的表, 只包含子类特有属性映射的字段)。实现这种策略的时候,有如下步骤: 父类用普通<class>标签定义即可 子类用<union-subclass>标签定义,在定义union-subclass的时候,需要注意如下几点: Union-subclass标签不再需要包含key标签(与joined-subclass不同) Union-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系), 也可以与class标签平行。 当Union-subclass标签的定义与class标签平行的时候,需要在Union-subclass标签中,添加extends属性,里面的值是父类的全路径名称。 子类的其它属性,像普通类一样,定义在Union-subclass标签的内部。这个时候,虽然在union-subclass里面定义的只有子类的属性,但是因为它继承了父类,所以, 不需要定义其它的属性,在映射到数据库表的时候,依然包含了父类的所有属性的映射字段。 !!!特别注意:在保存对象的时候,id不能重复(所以不能用自增方法生成主键) 2、存储和多态查询参见策略一:每棵类继承树对应一张表
这里我们将Animal定义为抽象类:
package com.lwf.hibernate.extend1; //public class Animal { //public class Animal { //第三种策略的时候设为abstract来测试 public abstract class Animal { private int id; private String name; private boolean 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 boolean isSex() { return sex; } public void setSex(boolean sex) { this.sex = sex; } }
其它类相同.
映射文件:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.lwf.hibernate.extend1"> <class name="Animal" abstract="true"> <id name="id"> <generator class="assigned"/> </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> </hibernate-mapping>
注意文件中使用了,union-subclass,并且没有了key属性.
而且Animal的主键生成策略变成了assigned.
所以跟着我们的测试文件的save数据方法也要变.
测试类:
package com.lwf.hibernate.test; import java.util.Iterator; import java.util.List; import junit.framework.TestCase; import org.hibernate.Session; import com.lwf.hibernate.extend1.Animal; import com.lwf.hibernate.extend1.Bird; import com.lwf.hibernate.extend1.Pig; import com.lwf.hibernate.util.HibernateUtils; public class Ext3Test extends TestCase { /** * 保存数据 * */ public void testSaveAnimal() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Pig p = new Pig(); p.setId(1); p.setName("猪1"); p.setSex(true); p.setWeight(400); Bird b = new Bird(); b.setId(2); b.setName("孔雀"); b.setSex(true); b.setHeight(100); session.save(p); session.save(b); session.getTransaction().commit(); }catch(Exception e) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } } /** * 通过Pig类来装载 * */ public void testLoad1() { Session session = null; try { session = HibernateUtils.getSession(); Pig p = (Pig)session.load(Pig.class, 1); System.out.println("name=" + p.getName()); }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } /** * 通过Animal类来装载 * */ public void testLoad2() { Session session = null; try { session = HibernateUtils.getSession(); Animal a = (Animal)session.load(Animal.class, 1); System.out.println("name=" + a.getName()); }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } public void testLoad3() { Session session = null; try { session = HibernateUtils.getSession(); Animal a = (Animal)session.load(Animal.class, 1); //因为我们load默认是Lazy,因为Lazy所以我们看到的是Animal的代理类 //所以通过instance是具体反映不出真正的对象类型的 if (a instanceof Pig) { System.out.println("name=" + a.getName()); }else { System.out.println("不是猪!"); } }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } public void testLoad4() { Session session = null; try { session = HibernateUtils.getSession(); Animal a = (Animal)session.get(Animal.class, 1); //可以正确判断,因为Animal不是代理类 if (a instanceof Pig) { System.out.println("name=" + a.getName()); }else { System.out.println("不是猪!"); } }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } /** * 将Animal的lazy设置为false * */ public void testLoad5() { Session session = null; try { session = HibernateUtils.getSession(); Animal a = (Animal)session.load(Animal.class, 1); if (a instanceof Pig) { System.out.println("name=" + a.getName()); }else { System.out.println("不是猪!"); } }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } public void testLoad6() { Session session = null; try { session = HibernateUtils.getSession(); /** * 多态查询 */ List animalList = session.createQuery("from Animal").list(); for (Iterator iter = animalList.iterator(); iter.hasNext(); ) { Animal a = (Animal)iter.next(); System.out.println("name=" + a.getName()); } }catch(Exception e) { e.printStackTrace(); }finally { HibernateUtils.closeSession(session); } } }
我们看看创建的表格:
mysql> desc t_bird; +--------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | | | | name | varchar(255) | YES | | NULL | | | sex | bit(1) | YES | | NULL | | | height | int(11) | YES | | NULL | | +--------+--------------+------+-----+---------+-------+ 4 rows in set (0.03 sec) mysql> desc t_pig; +--------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | | | | name | varchar(255) | YES | | NULL | | | sex | bit(1) | YES | | NULL | | | weight | int(11) | YES | | NULL | | +--------+--------------+------+-----+---------+-------+
你会发现因为父类为抽象类,所以并没有生成t_animal表,而子类中有了所有属性,生成的表中也有了所有的字段.这与前面二种策略是不同的.