用户操作
[即时聊天] [发私信] [加为好友]
胡圆平ID:mike1983
34681次访问,排名3356好友0人,关注者1
mike1983的文章
原创 64 篇
翻译 1 篇
转载 17 篇
评论 7 篇
最近评论
mike1983:不知道你什么时候出现这个问题的,我没遇到过这种情况,或者你可以把代码贴出来看看
keephope:LZ可否遇到了把图片保存后

图片被蒙上了一层颜色的问题吗

如果遇到并解决了

可否将解决办法告诉我呢

我的邮箱是

lizhe1999@sohu.com
秋绿恋歌:写得不错,最近我也在学习设计模式,我想从.NET转向J2EE方向学习了,呵呵,加一下我的QQ:87961327
junglesong:不錯,挺有意思的。
零度海洋:更多.net相關技術,plugins...大量實例
http://www.zero163.com
文章分类
收藏
相册
Your World to Warcraft 3 Needs!
ASP.NET
【孟宪会之精彩世界】
dotnet.csdn.net 团队blog
LoveCherry的Blog---DataGrid
Microsoft patterns & practices Enterprise Library系列分析文章
Nhibernate Map 说明文档
PetShop MVC结构分析
Programming For Life
TerryLee专栏
微软IE控件TreeView相关
思归呓语
英雄好汉的布拉格
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 Eclipse快速上手Hibernate--4. 继承映射(1) 收藏

新一篇: NDoc的使用说明!  | 旧一篇: nhibernate入门系列: 使用Criteria载入对象

Eclipse快速上手Hibernate--4. 继承映射(1)
   前面的《Eclipse快速上手Hibernate--1. 入门实例 》等三篇文章已经谈了Hibernate的入门以及利用工具创建的方法。这篇文章主要说说在Hibernate中的继承映射。相关配置请参考前三篇文章
 
   如果程序中的对象含有继承的关系,在Hibernate中有以下三种策略将这种关系映射到数据表上:
· 每个类层次结构一个表(table per class hierarchy)
· 每个子类一个表(table per subclass)
· 每个具体类一个表(table per concrete class)(有一些限制)
 
   每个类层次结构一个表的方式是将所有继承同一父类别的对象储存在同一个表格中,为了做到这一点,需要在表格中使用识别字段来表示某一列(row)是属于某个子类别或父类别,在这个主题中我们将先说明这个方法。
 
1. 创建项目
 
·  新建一个Java项目:InheritanceMapping,注意选中“创建单独的源文件夹和输出文件夹”,同时添加“用户库”:hibernate。 
 
 
2. 编写类文件
 
·  新建一个类,包名:javamxj.inheritance.one,类名:Animal。然后在生成的代码中添加变量,再利用“生成 Getter 和 Setter”,具体方式同《Eclipse快速上手Hibernate--1. 入门实例 》文章中的编辑User.java的方式一样。

Animal.java

/*
 * Hibernate - 继承映射(每个类层次一个表)
 * 创建日期 2005-4-9
 * @author javamxj(分享java快乐)
 * @link  Blog: htpp://javamxj.mblogger.cn  
 *              htpp://blog.csdn.net/javamxj/ 
 */
package javamxj.inheritance.one;

/**
 * @hibernate.class 
 *   table="Animal" 
 *   discriminator-value="Animal"
 * @hibernate.discriminator 
 *   column="ANIMAL_TYPE" 
 *   type="string" 
 *   length = "10"
 */
public abstract class Animal {
	private Long id;

	private String name;

	/**
	 * @hibernate.id 
	 *   column="ID" 
	 *   generator-class="hilo" 
	 *   unsaved-value="null"
	 */
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @hibernate.property 
	 *   length = "24"
	 */
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void makeSound();
}
 ·  这个类是父类,值得注意是在类层次标记中添加了一个discriminator标记,并用它定义了一个字段“ANIMAL_TYPE”,这个字段就是用来识别某一列(row)是属于某个子类别或父类别的。
 
 
·  子类Cat.java
Cat.java
package javamxj.inheritance.one;

/**
 * @hibernate.subclass 
 *   discriminator-value="Cat"
 */
public class Cat extends Animal {
	private String FurColor;

	public void makeSound() {
		System.out.println("喵喵");
	}

	/**
	 * @hibernate.property 
	 *   length = "24"
	 */
	public String getFurColor() {
		return FurColor;
	}

	public void setFurColor(String furColor) {
		FurColor = furColor;
	}
}
 
·  子类Dog.java
Dog.java
package javamxj.inheritance.one;

/**
 * @hibernate.subclass 
 *   discriminator-value="Dog"
 */
public class Dog extends Animal {
	private String category;

	public void makeSound() {
		System.out.println("汪汪");
	}

	/**
	 * @hibernate.property 
	 *   length = "24"
	 */
	public String getCategory() {
		return category;
	}

	public void setCategory(String category) {
		this.category = category;
	}
}
·  这两个子类都很简单,注意添加的hibernate.subclass的标记,指定其识别字段。
 
 
3. 构建文件Build.xml
 
·  在项目根目录下建立一个build.xml,要注意的是环境变量和数据库的设置要符合自己的实际配置,这里库文件目录的设置是"D:/java/Hibernate/lib",参考文章《Eclipse快速上手Hibernate--1. 入门实例》中的设置。
·  在MySQL中需要先建立一个HibernateTest数据库,为了解决中文问题,使用了GBK编码,注意“&”,这是由于XDoclet生成Hibernate配置文件时,会丢失一个“amp;”字符串(一个小Bug)。
·  这里我用build.xml中的“hibernatedoclet”任务直接生成“hibernate.cfg.xml”配置文件。

build.xml

<?xml version="1.0" encoding="GBK"?>
<project name="Hibernate中的继承映射" default="help" basedir=".">

	<!-- ******  环境设置,可以根据自己的实际配置自行更改 ***** -->
	<!-- 源文件目录, 可以通过 项目->属性->Java构建路径 更改 -->
	<property name="src.dir" value="./src" />
	<!-- 输出的class文件目录,可以通过 项目->属性->Java构建路径 更改 -->
	<property name="class.dir" value="./bin" />
	<!-- 库文件目录  -->
	<property name="lib.dir" value="D:/java/Hibernate/lib" />
	
	<!-- ******  数据库设置,可以根据自己的实际配置自行更改 ***** -->	
	<property name="hibernate.dialect" value="net.sf.hibernate.dialect.MySQLDialect"></property>
	<property name="hibernate.driver" value="com.mysql.jdbc.Driver"></property>
	<!--    &amp;amp;    -->
	<property name="hibernate.jdbc.url" 
		value="jdbc:mysql://localhost:3306/HibernateTest?useUnicode=true&amp;amp;characterEncoding=GBK">
	</property>
	<property name="hibernate.username" value="root"></property>
	<property name="hibernate.password" value="javamxj"></property>
	<property name="hibernate.show.sql" value="true"></property>
	
	

	<!-- 定义类路径 -->
	<path id="project.class.path">
		<fileset dir="${lib.dir}">
			<include name="*.jar"/>
		</fileset>
		<pathelement location="${class.dir}" />
	</path>

	<!-- ************************************************************** -->
	<!-- 使用说明 -->
	<!-- ************************************************************** -->
	<target name="help">
		<echo message="利用工具开发Hibernate" />
		<echo message="-----------------------------------" />
		<echo message="" />
		<echo message="提供以下任务:" />
		<echo message="" />		
		<echo message="generate-hbm      --> 运行HibernateDoclet,生成 Hibernate 类的映射文件" />
		<echo message="schemaexportt     --> 运行SchemaExport,利用 hbm.xml 文件生成数据表" />
		<echo message="" />
	</target>



	<!-- ************************************************************** -->
	<!-- HibernateDoclet 任务 -->
	<!-- ************************************************************** -->
	<target name="generate-hbm" >
		<echo message="运行HibernateDoclet,生成 Hibernate 类的映射文件"/>

		<taskdef name="hibernatedoclet" 
			classname="xdoclet.modules.hibernate.HibernateDocletTask" 
			classpathref="project.class.path">
		</taskdef>

		<hibernatedoclet destdir="${src.dir}" 
			excludedtags="@version,@author,@todo" force="true" encoding="GBK" 
			verbose="true">

			<fileset dir="${src.dir}">
				<include name="**/*.java"/>
			</fileset>

			<hibernate version="2.0" xmlencoding="GBK" />	
			
			<!--   生成配置文件       -->
			<hibernatecfg
				dialect="${hibernate.dialect}"
				driver="${hibernate.driver}" 
				jdbcUrl="${hibernate.jdbc.url}" 
				userName="${hibernate.username}" 
				password="${hibernate.password}"
				showSql="${hibernate.show.sql}"
				xmlencoding="GBK"
			/>			
			
		</hibernatedoclet>		
	</target>


	<!-- ************************************************************** -->
	<!-- SchemaExport 任务 -->
	<!-- ************************************************************** -->
	<target name="schemaexport">
		<echo message="运行SchemaExport,利用 hbm.xml 文件生成数据表"/>

		<taskdef name="schemaexport" 
			classname="net.sf.hibernate.tool.hbm2ddl.SchemaExportTask" 
			classpathref="project.class.path">
		</taskdef>

		<schemaexport config="${src.dir}/hibernate.cfg.xml" quiet="no" 
			text="no" drop="no" output="schema-export.sql">
		</schemaexport>
	</target>

</project>
 
 
· 好了,只要这四个文件就够了,其它的会自动生成的。整个项目的结构如下:
 
 
 
4. 运行任务
 
·  双击“generate-hbm”任务,会发现在包中多了一个Animal.hbm.xml文件,在src目录下会多了一个hibernate.cfg.xml文件,如果没有,按F5键刷新一下(这里建议打开Eclipse的“首选项”对话框,在“工作台”中勾选“自动刷新工作空间”和“在构建之前自动保存”这两项,这样以后不用每次都刷新了)。

Animal.hbm.xml

<?xml version="1.0" encoding="GBK"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping
>
    <class
        name="javamxj.inheritance.one.Animal"
        table="Animal"
        dynamic-update="false"
        dynamic-insert="false"
        select-before-update="false"
        optimistic-lock="version"
        discriminator-value="Animal"
    >

        <id
            name="id"
            column="ID"
            type="java.lang.Long"
            unsaved-value="null"
        >
            <generator class="hilo">
              <!--  
                  To add non XDoclet generator parameters, create a file named 
                  hibernate-generator-params-Animal.xml 
                  containing the additional parameters and place it in your merge dir. 
              --> 
            </generator>
        </id>

        <discriminator
            column="ANIMAL_TYPE"
            type="string"
            length="10"
        />

        <property
            name="name"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="name"
            length="24"
        />

        <!--
            To add non XDoclet property mappings, create a file named
                hibernate-properties-Animal.xml
            containing the additional properties and place it in your merge dir.
        -->
        <subclass
            name="javamxj.inheritance.one.Cat"
            dynamic-update="false"
            dynamic-insert="false"
            discriminator-value="Cat"
        >

        <property
            name="furColor"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="furColor"
            length="24"
        />

	    <!--
            	To add non XDoclet property mappings, create a file named
                hibernate-properties-Cat.xml
		containing the additional properties and place it in your merge dir.
	    -->

        </subclass>
        <subclass
            name="javamxj.inheritance.one.Dog"
            dynamic-update="false"
            dynamic-insert="false"
            discriminator-value="Dog"
        >

        <property
            name="category"
            type="java.lang.String"
            update="true"
            insert="true"
            access="property"
            column="category"
            length="24"
        />

	    <!--
            	To add non XDoclet property mappings, create a file named
                hibernate-properties-Dog.xml
		containing the additional properties and place it in your merge dir.
	    -->

        </subclass>

    </class>

</hibernate-mapping>
 
 
hibernate.cfg.xml
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE hibernate-configuration 
  PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" 
  "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">

<!-- Generated file - Do not edit! -->

<hibernate-configuration>

	<!-- a SessionFactory instance listed as /jndi/name -->
	<session-factory>

		<!-- properties -->
		<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
		<property name="show_sql">true</property>
		<property name="use_outer_join">false</property>
		<property name="connection.username">root</property>
		<property name="connection.password">javamxj</property>
		<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
	           <property name="connection.url">jdbc:mysql://localhost:3306/HibernateTest?useUnicode=true&amp;characterEncoding=GBK</property>

		<!-- mapping files -->
		<mapping resource="javamxj/inheritance/one/Animal.hbm.xml"/>
	</session-factory>

</hibernate-configuration>
 
·  双击“schemaexport”任务,在项目根目录下,会产生一个“schema-export.sql”文件。
schema-export.sql
drop table if exists Animal
drop table if exists hibernate_unique_key
create table Animal (
   ID bigint not null,
   ANIMAL_TYPE varchar(10) not null,
   name varchar(24),
   furColor varchar(24),
   category varchar(24),
   primary key (ID)
)
create table hibernate_unique_key (
    next_hi integer
)
insert into hibernate_unique_key values ( 0 )
 
·  切换到数据库中,会发现已经自动产生了数据表animal(表hibernate_unique_key是由于采用hilo主键策略生成的)。
 
 
5. 测试程序
 
·  好了,在包javamxj.inheritance.one下新建一个Demo.java类,很简单,前半部分是添加数据,后半部分是简单的测试。

Demo.java

package javamxj.inheritance.one;

import java.util.Iterator;
import java.util.List;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;

public class Demo {
	public static void main(String[] args) {
		try {
			new Demo();
		} catch (HibernateException he) {
			he.printStackTrace();
		}
	}

	public Demo() throws HibernateException {
		
		SessionFactory sf = new Configuration().configure()
				.buildSessionFactory();

		Session sess = sf.openSession();
		Transaction tx = null;
		try {
			tx = sess.beginTransaction();

			Cat cat = new Cat();
			cat.setName("小白");
			cat.setFurColor("白色");
			sess.save(cat);

			Dog dog = new Dog();
			dog.setName("小黑");
			dog.setCategory("京巴狗");
			sess.save(dog);

			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			throw e;
		} finally {
			sess.close();
		}

		sess = sf.openSession();
		tx = null;
		try {
			tx = sess.beginTransaction();
			List animals = sess.find("from " + Animal.class.getName());
			for (Iterator it = animals.iterator(); it.hasNext();) {
				Animal animal = (Animal) it.next();
				System.out.println("动物 '" + animal.getName()
						+ "' 所在类是: " + animal.getClass().getName());
				System.out.print("发出叫声: ");
				animal.makeSound();

			}

			tx.commit();
		} catch (HibernateException e) {
			if (tx != null)
				tx.rollback();
			throw e;
		} finally {
			sess.close();
		}
	}
}
 
 
·  运行这个类,控制台输出如下:
 
·  同时,数据表中生成如下数据:
注意其中为“NULL”的部分。
 
·  最后的项目结构如下:
 
 
小结:  
● 优点:
· 实现简单。
· 支持多态——对象角色发生变化,或存在多重角色时。
· 报表操作实现简单:表中包含了所有信息。

● 缺点:
· 增加类层次中的耦合。类层次中任何类的属性的增加都会导致表的变更;某个子类属性的修改会影响到整个
层次结构,而不仅仅是该子类。
· 浪费了一些数据库空间。浪费空间的多少取决于继承层次的深度。层次越深,不同的属性越多,属性的全集就越大,也就越浪费空间。
· 可能需要指明具体的角色。
 
 
参考:
· HIBERNATE - 符合Java习惯的关系数据库持久化(第8章)
 
  下篇文章会谈谈每个子类一个表的策略。

发表于 @ 2005年07月22日 13:25:00|评论(loading...)|编辑

新一篇: NDoc的使用说明!  | 旧一篇: nhibernate入门系列: 使用Criteria载入对象

评论:没有评论。

发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © mike1983