`

Hibernate之实体层次设计

阅读更多

继承是关系型数据与面向对象数据结构之间的主要差异之一,如何在关系型的数据之上可以像面向对象数据那样清晰的表达之间的逻辑关系;Hiberante中支持3种类型的继承形式:

 

  • table per concrete class(表与子表之间的独立一对一关系)

在面向对象的设计中会有继承关系,在hibernate可以这么来实现:比如,一个电子商务网站会出售DVD和Book,它们的共性就是会有名字和厂商,而不同之处在于DVD会有区域码,而book会有作者;那么在面向对象的设计中,我们会想将共性构造一个基类,然后在对基类进行扩展如:

父类TItem:

 

public class TItem implements java.io.Serializable{
	private Integer id;
	private String name;
	private String company;
        get()/set()
}

子类TBook:

 

public class TBook extends TItem {
	private String author;
        get()/set()
}

 

 子类TDvd:

 

public class TDvd extends TItem {
	private String regionCode;
        get()/set()
}

 

 在*.hbm.xml中直接这么定义:

TBook.hbm.xml:

 

<hibernate-mapping package="com.keith.tablePerConcreteClass">
	<class name="TBook" table="TBook">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name" />
		<property name="company" />
		<property name="author" />
	</class>
</hibernate-mapping>

 

 TDvd.hbm.xml:

 

<hibernate-mapping package="com.keith.tablePerConcreteClass">
	<class name="TDvd" table="TDvd">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name" />
		<property name="company" />
		<property name="regionCode" />
	</class>
</hibernate-mapping>

 

 测试下:添加数据:

 

		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		TBook book = new TBook();
		book.setName("java Code");
		book.setAuthor("king");
		book.setCompany("EN");
		
		TDvd dvd = new TDvd();
		dvd.setName("2012");
		dvd.setRegionCode("0404040404");
		dvd.setCompany("ZH");
		
		session.save(book);
		session.save(dvd);
		session.getTransaction().commit();

 

 日志中这样输出:

 

    create table TBook (
        id integer not null auto_increment,
        name varchar(255),
        company varchar(255),
        author varchar(255),
        primary key (id)
    )
 

 

 

    create table TDvd (
        id integer not null auto_increment,
        name varchar(255),
        company varchar(255),
        regionCode varchar(255),
        primary key (id)
    )

 

 

 Hibernate: insert into  TBook(name, company, author) values (?, ?, ?)
Hibernate:insert  into  TDvd (name, company, regionCode) values (?, ?, ?)

 党我们查询时:

 

	        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		List list =session.createQuery("from com.keith.tablePerConcreteClass.TItem").list();
		Iterator it = list.iterator();
		while (it.hasNext()) {
			TItem item = (TItem) it.next();
			System.out.println(item.getName());
		}
		session.getTransaction().commit();	

 

 看下输出的日志:

 

Hibernate: 
    select
        tbook0_.id as id0_,
        tbook0_.name as name0_,
        tbook0_.company as company0_,
        tbook0_.author as author0_ 
    from
        TBook tbook0_
Hibernate: 
    select
        tdvd0_.id as id1_,
        tdvd0_.name as name1_,
        tdvd0_.company as company1_,
        tdvd0_.regionCode as regionCode1_ 
    from
        TDvd tdvd0_

 

 查询了2个表的内容,结果是:

 

java Code
2012

 通过这样的方式我们将继承关系在持久层得到体现,可是如果我们要根据name类查询某件商品,这是会将所有的表全部查询一遍,然后进行汇总,如果这样的,性能大大的降低!

 

  • table per subclass(每个子表对应一张子表,并与主类共享主表)

如果父类表发生变化,那么其子类就得跟着变化,这样太不灵活,我们可以将父类表(TItem)单独映射到一个主表中,而为TBook,TDvd分别单独设立一张子表,子表中包含所扩展的属性,同时子表和父表可以通过关系型数据库的外键想关联;

对象没有变化,还是上面那么种写法,既然父类是一个主表了,子类是扩展属性的那么我们就根据外键来执行相应的操作;

这里只需要一个TItem.hbm.xml:

 

<hibernate-mapping package="com.keith.tablePerSubclass">
	<class name="TItem" table="TItem">
		<id name="id" type="java.lang.Integer" column="TItem_id">
			<generator class="native"/>
		</id>
		<property name="name" />
		<property name="company" />
		
		<joined-subclass name="TBook" table="tBook">
			<key column="TItem_id"></key>
			<property name="author" />
		</joined-subclass>
		
		<joined-subclass name="TDvd" table="tDvd">
			<key column="TItem_id"></key>
			<property name="regionCode" />
		</joined-subclass>
	</class>
</hibernate-mapping>

 

 添加数据也后我们看下日志信息:首先会创建一个主表:

 

    create table TItem (
        TItem_id integer not null auto_increment,
        name varchar(255),
        company varchar(255),
        primary key (TItem_id)
    )

 

 tBook:

 

    create table tBook (
        TItem_id integer not null,
        author varchar(255),
        primary key (TItem_id)
    )

 

 tDvd:

 

    create table tDvd (
        TItem_id integer not null,
        regionCode varchar(255),
        primary key (TItem_id)
    )

 

 并对其子类进行关联:

 

23:00:33,791 DEBUG SchemaExport:377 - 
    alter table tBook 
        add index FK682557D53D2350B (TItem_id), 
        add constraint FK682557D53D2350B 
        foreign key (TItem_id) 
        references TItem (TItem_id)
23:00:33,842 DEBUG SchemaExport:377 - 
    alter table tDvd 
        add index FK35C8FE53D2350B (TItem_id), 
        add constraint FK35C8FE53D2350B 
        foreign key (TItem_id) 
        references TItem (TItem_id)

 

 添加时候也会按照下面的顺序来执行:

 

Hibernate: insert  into TItem(name, company) values(?, ?)
Hibernate:insert  into   tBook(author, TItem_id) values  (?, ?)

Hibernate: insert into TItem(name, company) values(?, ?)
Hibernate: insert into  tDvd(regionCode, TItem_id) values(?, ?)

 

 当我们查询的时候:

 

Hibernate: 
    select
        titem0_.TItem_id as TItem1_0_,
        titem0_.name as name0_,
        titem0_.company as company0_,
        titem0_1_.author as author1_,
        titem0_2_.regionCode as regionCode2_,
        case 
            when titem0_1_.TItem_id is not null then 1 
            when titem0_2_.TItem_id is not null then 2 
            when titem0_.TItem_id is not null then 0 
        end as clazz_ 
    from
        TItem titem0_ 
    left outer join
        tBook titem0_1_ 
            on titem0_.TItem_id=titem0_1_.TItem_id 
    left outer join
        tDvd titem0_2_ 
            on titem0_.TItem_id=titem0_2_.TItem_id

 会比上一种方法减少能源消耗!但是对于性能有很高的要求系统而言,以上2中方式都不可选,多表操作的性能消耗是十分可观的!

 

  • table per class hierarchy(表与类的一对多关系)

综合以上的考虑,我们可以这样设计,将两种实体映射到一个对象里,比如可以用category来区分;1就是dvd,2就是book;其中实体类应该这样写:

TItem:

 

public class TItem implements java.io.Serializable {
	private Integer id;
	private Integer category;
	private String name;
	private String company;
	private String regionCode;
	private String author;

	public TItem() {
	}
        get()/set()
}

 

 其映射文件可以这样TItem.hbm.xml

 

<hibernate-mapping package="com.keith.tablePerClassHierarchy">
	<class name="TItem" table="TItem">
		<id name="id" type="java.lang.Integer" column="TItem_id">
			<generator class="native"/>
		</id>
		<discriminator column="category" type="string"></discriminator>
		<property name="name" />
		<property name="company" />
		
		<subclass name="TDvd" discriminator-value="1">
			<property name="regionCode" />
		</subclass>
		
		<subclass name="TBook" discriminator-value="2">
			<property name="author" />
		</subclass>
	</class>
</hibernate-mapping>

 

当我们添加一个对象时:

先看下建表SQL:

 

    create table TItem (
        TItem_id integer not null auto_increment,
        category varchar(255) not null,
        name varchar(255),
        company varchar(255),
        regionCode varchar(255),
        author varchar(255),
        primary key (TItem_id)
    )

 

 添加数据的SQL:

 

Hibernate: 
    insert 
    into
        TItem
        (name, company, category) 
    values
        (?, ?, 'com.keith.tablePerClassHierarchy.TItem')

Hibernate: 
    insert 
    into
        TItem
        (name, company, category) 
    values
        (?, ?, 'com.keith.tablePerClassHierarchy.TItem')

 

 当我们查询的时候:

 

Hibernate: 
    select
        tbook0_.TItem_id as TItem1_0_,
        tbook0_.name as name0_,
        tbook0_.company as company0_,
        tbook0_.author as author0_ 
    from
        TItem tbook0_ 
    where
        tbook0_.category='2'

Hibernate: 
    select
        tdvd0_.TItem_id as TItem1_0_,
        tdvd0_.name as name0_,
        tdvd0_.company as company0_,
        tdvd0_.regionCode as regionCode0_ 
    from
        TItem tdvd0_ 
    where
        tdvd0_.category='1'

 自己就默认找到了!

附上源文件,及测试代码!

分享到:
评论

相关推荐

    hibernate独立开发包

    10. **继承映射**:Hibernate允许实体类之间进行单表继承、联合继承和多表继承,以适应不同层次的类结构。 11. **延迟加载(Lazy Loading)**:为提高性能,Hibernate提供了延迟加载机制,只有当真正需要访问关联...

    Hibernate+程序设计ppt课件

    4. **对JDBC的封装**:Hibernate在JDBC之上进行了抽象和封装,使得开发者可以使用更高层次的API来操作数据库,而无需编写复杂的SQL语句。 5. **在分层架构中的位置**:在传统的三层架构中,Hibernate通常作为持久化...

    Hibernate教程03_Hibernate核心开发接口介绍

    Hibernate是一个强大的Java对象关系映射(ORM)框架,它消除了传统SQL编程的繁琐,提供了更高层次的抽象,使我们能够用面向对象的方式处理数据。 1. **SessionFactory接口**: SessionFactory是Hibernate的核心组件...

    hibernate实现递归查询

    综上所述,通过合理设计实体关系,使用HQL或Criteria API,结合数据库特性和缓存策略,我们可以有效地在Hibernate中实现递归查询,处理树形结构数据。理解递归查询的原理并掌握其实践技巧,对于提升Java企业级应用的...

    HIBERNATE - 符合Java习惯的关系数据库持久化

    Hibernate是Java领域内最受欢迎的对象关系映射(ORM)框架之一,它简化了Java应用程序与关系型数据库之间的交互,使得开发人员能够用面向对象的方式处理数据库操作,而无需深入了解SQL语法或数据库API。通过将Java...

    hibernate 3.1源代码

    在Hibernate 3.1中,这种映射主要通过Hibernate的配置文件(通常是hibernate.cfg.xml)和实体类的注解或XML映射文件(如.hbm.xml)来实现。 `hibernate3.1参考手册中文版.pdf` 这份文档是开发者理解和使用Hibernate...

    韩顺平Hibernate笔记

    3. **实体类和映射文件**:讲解如何创建Java实体类,以及对应的Hibernate映射文件(.hbm.xml),理解实体类属性与数据库表字段的对应关系。 4. **Session工厂和Session**:解析SessionFactory和Session的用法,理解...

    用Hibernate映射继承关系

    本主题聚焦于“用Hibernate映射继承关系”,我们将深入探讨Hibernate如何处理对象的继承层次结构,并将其映射到数据库中的表。 Hibernate支持多种继承策略,包括单一表继承(Single Table Inheritance)、联合表...

    hibernate的多态查询

    2. **实体类和继承层次结构**:在Hibernate中,实体类可以构成继承关系,通过`@Inheritance`注解来定义继承策略,如SINGLE_TABLE、JOINED、TABLE_PER_CLASS等。不同的策略会影响数据库表的设计和查询的方式。 3. **...

    hibernate父亲与孩子

    同时,我们可以利用Hibernate的Criteria API或HQL(Hibernate Query Language)来编写高效的查询,以获取特定层次或路径的节点。 5. **缓存策略**:对于大型树结构,缓存策略的设置至关重要。Hibernate提供了第一级...

    hibernate程序高手秘笈-英文版

    1. **Hibernate基础知识**:首先,你会了解Hibernate的基本概念,包括其设计理念、核心组件以及如何在项目中集成Hibernate。这包括Hibernate的配置文件、实体类、持久化对象(POJOs)、映射文件等基本元素。 2. **...

    基于Hibernate实现的学生选课系统

    2. **实体类(Student、Course、Enrollment)**:这些类代表数据库中的表,通过注解@Entity声明为Hibernate管理的实体。每个实体类的属性与数据库表的字段相对应,使用@Column注解进行详细配置。 3. **持久化类的ID*...

    Hibernate双向一对多经典实例

    本实例将聚焦于Hibernate中的一对多关系,这是一种常见的关联类型,尤其是在处理具有层次结构的数据时。双向一对多关系意味着一个实体可以拥有多个相关联的实体,同时每个相关联的实体也可以回指到原始实体。 **...

    深入浅出Hibernate

    ### 深入浅出Hibernate:实体的...而在实体层次设计方面,通过恰当的继承关系设计,可以使系统既保持良好的可扩展性,又能在性能方面得到优化。总之,正确地设计实体类对于开发高效稳定的 Hibernate 应用程序至关重要。

    struts1.2 + spring2.5 + hibernate3.2框架demo

    Struts1.2、Spring2.5和Hibernate3.2是经典的Java企业级开发框架组合,它们各自在应用程序的不同层次上发挥着重要作用。Struts1.2是一个MVC(Model-View-Controller)框架,主要负责处理用户界面与业务逻辑之间的...

    Hibernate 单表实现树结构

    这样的设计使得单个表能够表示层次关系。 接着,为了在Hibernate中正确地映射这种关系,我们需要在实体类上添加对应的注解。@ManyToOne注解用于表示一对多的关系,这里表示当前节点与父节点的关系;@JoinColumn注解...

    hibernate-release-4.3.8.Final

    Hibernate,作为Java领域中最流行的持久化框架之一,自推出以来就以其强大的对象关系映射(ORM)能力赢得了广大开发者的心。本文将深入探讨Hibernate 4.3.8.Final版本中的核心概念、功能特性以及实际开发中的应用...

Global site tag (gtag.js) - Google Analytics