本示例演示Hibernate继承映射的第一种策略:每棵类继承树对应一张表 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便能根据这个鉴别字段正确的加载对象 3、理解何为多态查询,即hibernate能够加载数据的时候自动鉴别其真正的类型 多态get(),支持 多态load(),设置Lazy=“false”时,支持 多态查询,支持
配置如下:
测试的话先在mysql下创建数据库hibernate.再配置好下列文件放在src根目录
hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">sys833199</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">True</property> <property name="format_sql">True</property> <property name="use_sql_comments">True</property> <mapping resource="com/lwf/hibernate/extend1/ext1.hbm.xml"/> </session-factory> </hibernate-configuration>
log4j.properties
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file hibernate.log ### #log4j.appender.file=org.apache.log4j.FileAppender #log4j.appender.file.File=hibernate.log #log4j.appender.file.layout=org.apache.log4j.PatternLayout #log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=warn, stdout #log4j.logger.org.hibernate=info #log4j.logger.org.hibernate=debug ### log HQL query parser activity #log4j.logger.org.hibernate.hql.ast.AST=debug ### log just the SQL #log4j.logger.org.hibernate.SQL=debug ### log JDBC bind parameters ### log4j.logger.org.hibernate.type=info #log4j.logger.org.hibernate.type=debug ### log schema export/update ### log4j.logger.org.hibernate.tool.hbm2ddl=debug ### log HQL parse trees #log4j.logger.org.hibernate.hql=debug ### log cache activity ### #log4j.logger.org.hibernate.cache=debug ### log transaction activity #log4j.logger.org.hibernate.transaction=debug ### log JDBC resource acquisition #log4j.logger.org.hibernate.jdbc=debug ### enable the following line if you want to track down connection ### ### leakages when using DriverManagerConnectionProvider ### #log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
ext1.hbm.xml
这里配置按照继承映射第一种策略进行,即父类与子类映射到同一个表中,表中有一个字段来标识属于哪一个子类.
<?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" table="t_animal"> <id name="id"> <generator class="native"></generator> </id> <discriminator column="type" type="string"/> <property name="name"/> <property name="sex"/> <subclass name="Bird" discriminator-value="bird"> <property name="height"/> </subclass> <subclass name="Pig" discriminator-value="pig"> <property name="weight"/> </subclass> </class> </hibernate-mapping>
Animal类
package com.lwf.hibernate.extend1; public 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; } }
package com.lwf.hibernate.extend1; public class Bird extends Animal { private int height; public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } }
package com.lwf.hibernate.extend1; public class Pig extends Animal { private int weight; public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } }
上面文件建立好后,使用ExportDB类创建表.
package com.lwf.hibernate.util; import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; public class ExportDB { public static void main(String[] args) { //读取配置文件 Configuration cfg = new Configuration().configure(); //创建SchemaExport对象 SchemaExport export = new SchemaExport(cfg); //创建数据库表 export.create(true,true); } }
建立工具类:
package com.lwf.hibernate.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtils { private static SessionFactory factory; private HibernateUtils() {} static { Configuration cfg = new Configuration().configure(); factory = cfg.buildSessionFactory(); } public static SessionFactory getSessionFactory() { return factory; } public static Session getSession() { return factory.openSession(); } public static void closeSession(Session session) { if (session != null) { if (session.isOpen()) { session.close(); } } } }
以下是我的测试类:
package com.lwf.hibernate.test; import java.util.Iterator; import java.util.List; 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 Ext1Test { public static void main(String[] args) { // testSaveAnimal(); // testLoad1(); // testLoad2(); testLoad3(); testLoad4(); // testLoad5(); // testLoad6(); } /** * 保存数据 * */ public static void testSaveAnimal() { Session session = null; try { session = HibernateUtils.getSession(); session.beginTransaction(); Pig p = new Pig(); p.setName("猪1"); p.setSex(true); p.setWeight(400); Bird b = new Bird(); 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 static 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 static 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 static 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 static 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 static 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 static void testLoad6() { Session session = null; try { session = HibernateUtils.getSession(); /** * 多态查询 */ List animalList = session.createQuery("from com.lwf.hibernate.extend1.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); } } }
要通过对每一个测试方法的运行才能将最开始的描述有更深的认识.
上面测试类中testLoad3与testLoad4比较得知: 多态get(),支持
testLoad3与testLoad5比较得知:多态load(),设置Lazy=“false”时,支持