Hibernate继承映射一:每个类分层结构一张表

本示例演示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”时,支持

你可能感兴趣的:(数据结构,sql,Hibernate,log4j,mysql)