1、整个继承树映射到一张表
在一个论坛中有用户(User)这个实体类,其中User这个实体中有分为普通用户,管理员与游客这3种身份,而这3种现在身份的用户就只有一个字段(即类型)不相同,可以考虑用Hibernate中的Table per class hierarchy策略
对象模型(Java类结构)
表结构
User代码:
package org.hibernate.domain; import java.util.Date; /** * 实体类 */ public class User { private int id; private String name; private Date birthday; 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 Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", birthday=" + birthday + "]"; } }
Admin代码:
package org.hibernate.domain; public class Admin extends User { private String admin; public String getAdmin() { return admin; } public void setAdmin(String admin) { this.admin = admin; } }
package org.hibernate.domain; public class Guest extends User { private String guest; public String getGuest() { return guest; } public void setGuest(String guest) { this.guest = guest; } }
配置文件:
<?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="org.hibernate.domain"> <class name="User" table="user" discriminator-value="0"> <id name="id"> <generator class="native" /> </id> <!-- 默认为string类型,这里指定为int类型 --> <discriminator column="type" type="int" /> <property name="name" /> <property name="birthday" /> <subclass name="Admin" discriminator-value="1"> <property name="admin" column="admin" /> </subclass> <subclass name="Guest" discriminator-value="2"> <property name="guest" column="guest" /> </subclass> </class> </hibernate-mapping>
测试类:
package org.hibernate.test; import junit.framework.TestCase; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.domain.Admin; import org.hibernate.domain.Guest; import org.hibernate.domain.User; import org.hibernate.util.HibernateUtil; public class TestUser extends TestCase { public void testAddUser() { Session session = null; Transaction tx = null; try { User user = new User(); user.setName("user1"); Admin admin = new Admin(); admin.setName("user2"); admin.setAdmin("admin user"); Guest guest = new Guest(); guest.setName("user3"); guest.setGuest("guest user"); session = HibernateUtil.getSession(); tx = session.beginTransaction(); session.save(user); session.save(admin); session.save(guest); tx.commit(); } finally { if (session != null) session.close(); } } public void testQuery() { Session session = null; Transaction tx = null; try { session = HibernateUtil.getSession(); tx = session.beginTransaction(); session.get(User.class, 1); tx.commit(); } finally { if (session != null) session.close(); } } }
testAddUser方法测试结果:
Hibernate: insert into user (name, birthday, type) values (?, ?, 0) Hibernate: insert into user (name, birthday, admin, type) values (?, ?, ?, 1) Hibernate: insert into user (name, birthday, guest, type) values (?, ?, ?, 2)
可以看到3个对象都保存在了同一张表(User)中,其中靠type字段来区分不同的用户
User表记录如下
现在我们测试testQuery方法,结果如下:
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.birthday as birthday0_0_, user0_.admin as admin0_0_, user0_.guest as guest0_0_, user0_.type as type0_0_ from user user0_ where user0_.id=?
将测试代码中的
session.get(User.class, 1);
更改为
session.get(User.class, 2);
则结果如下:
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.birthday as birthday0_0_, user0_.admin as admin0_0_, user0_.guest as guest0_0_, user0_.type as type0_0_ from user user0_ where user0_.id=?
因为hibernate支持多态查询,故查询语句不变
将测试代码中的
session.get(User.class, 2);
更改为
session.get(Guest.class, 2);
则结果如下:
Hibernate: select guest0_.id as id0_0_, guest0_.name as name0_0_, guest0_.birthday as birthday0_0_, guest0_.guest as guest0_0_ from user guest0_ where guest0_.id=? and guest0_.type=2
从上述结果可以看到如果是明确知道查询是哪一类用户,则查询语句后面会指定type类型
采用这种策略只需要一张表即可。它有一个很大的限制:要求那些由子类定义的字段, 如admin
,不能有非空(NOT NULL)
约束。
2、每个类映射到一张表
可以看到Hibernate整个类映射到一张表策略中,如果子类中有很多字段的情况下,则表就会产生很多的空字段,由此当子类中有很多字段的情况下,可以采用“每个子类一张表”的映射策略
表结构如下:
修改User.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="org.hibernate.domain"> <class name="User" table="user"> <id name="id" column="userId"> <generator class="native" /> </id> <property name="name" /> <property name="birthday" /> <joined-subclass name="Admin" table="admin"> <key column="userId" /> <property name="admin" column="admin" /> </joined-subclass> <joined-subclass name="Guest" table="guest"> <key column="userId" /> <property name="guest" column="guest" /> </joined-subclass> </class> </hibernate-mapping>
测试类:
package org.hibernate.test; import junit.framework.TestCase; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.domain.Admin; import org.hibernate.domain.Guest; import org.hibernate.domain.User; import org.hibernate.util.HibernateUtil; public class TestUser extends TestCase { public void testAddUser() { Session session = null; Transaction tx = null; try { User user = new User(); user.setName("user1"); Admin admin = new Admin(); admin.setName("user2"); admin.setAdmin("admin user"); Guest guest = new Guest(); guest.setName("user3"); guest.setGuest("guest user"); session = HibernateUtil.getSession(); tx = session.beginTransaction(); session.save(user); session.save(admin); session.save(guest); tx.commit(); } finally { if (session != null) session.close(); } } public void testQuery() { Session session = null; Transaction tx = null; try { session = HibernateUtil.getSession(); tx = session.beginTransaction(); session.get(User.class, 1); tx.commit(); } finally { if (session != null) session.close(); } } }
testAddUser方法测试结果:
Hibernate: insert into user (name, birthday) values (?, ?) Hibernate: insert into user (name, birthday) values (?, ?) Hibernate: insert into admin (admin, userId) values (?, ?) Hibernate: insert into user (name, birthday) values (?, ?) Hibernate: insert into guest (guest, userId) values (?, ?)
当插入的用户不是普通用户的时候,需要往2张表中插入数据
相关推荐
标题:“Hibernate继承关系映射.pdf” 描述:“简明扼要地介绍了Hibernate中继承关系的映射方式,深入探讨了三种不同的映射策略及其优缺点,同时解析了多态查询的概念。” 知识点: ### Hibernate继承关系映射...
本主题聚焦于“用Hibernate映射继承关系”,我们将深入探讨Hibernate如何处理对象的继承层次结构,并将其映射到数据库中的表。 Hibernate支持多种继承策略,包括单一表继承(Single Table Inheritance)、联合表...
在大型项目中,由于业务需求复杂,我们常常会使用到类的继承来组织代码结构,而Hibernate提供了对这些继承关系的映射支持。本主题将深入探讨"Hibernate继承映射+C3P0代码"的相关知识点。 首先,让我们理解Hibernate...
以下是对"jpa/hibernate继承注解"这一主题的详细说明。 1. **单一表继承(Single Table Inheritance, STI)** 单一表继承是最简单的继承策略,所有的子类信息都存储在一个数据库表中。使用`@Inheritance(strategy ...
Hibernate,作为Java中广泛使用的对象关系映射(ORM)框架,提供了多种方式来处理继承关系的映射,其中一种就是"每个类都对应一张表"的策略。本文将深入探讨这种映射方式,以及如何在Hibernate中实现它。 首先,...
本话题主要探讨的是Hibernate 3.2版本中的类继承关系处理,这是面向对象编程中常见的概念,但在数据库映射时需要特殊考虑。在Hibernate中,类继承关系的处理允许我们创建更加灵活和可扩展的对象模型。 在Hibernate ...
Hibernate继承映射是将Java类的继承关系映射到数据库表的一种策略,使得对象模型的复杂性能够平滑地转化为关系数据库模型。本篇将详细介绍Hibernate继承映射的第一种策略——每棵类继承树对应一张表,即单一表继承...
Hibernate继承映射是将Java中的继承关系映射到数据库的关系模型中。在Java中,一个基类可以有多个子类,而在数据库中,这些子类可以共享一张表或者各自拥有独立的表,这取决于我们选择的继承策略。Hibernate提供了四...
Hibernate一对一数据关联 Hibernate下的多对多关系 Hibernate关系映射 Hibernate继承关系映射 Hibernate映射类型-主键生成器-核心API Hibernate3 插件Eclipse配置
在Java的ORM框架Hibernate中,映射继承关系是常见的需求,尤其在处理具有层次结构的实体类时。本文将详细探讨Hibernate中处理继承关系的三种映射策略:subclass、joined-subclass以及union-subclass。 首先,让我们...
在实现这种映射时,我们需要在Hibernate的配置文件(hibernate.cfg.xml或相应的注解)中指定继承关系。例如,我们有一个抽象基类`Person`和两个子类`Student`和`Teacher`,可以这样配置: ```xml <hibernate-...
在传统的面向对象编程中,继承是实现代码复用和结构化设计的重要手段,而在关系型数据库中,由于其二维表格的特性,往往需要采用特定的方式来映射这种继承关系。本文将深入探讨使用注解配置的Hibernate继承映射策略...
6. **继承关系映射**:Hibernate支持类的继承关系映射,包括单表继承(Single Table Inheritance)、联合继承(Concrete Table Inheritance)和歧视值继承(Discriminator Value Inheritance)。单表继承所有子类...
《Hibernate继承映射详解》 在Java开发中,对象关系映射(ORM)框架如Hibernate大大简化了数据库操作。Hibernate不仅提供了对基本数据类型的映射,还支持复杂的数据结构,如继承关系的映射。本篇文章将深入探讨...
在ORM(Object-Relational Mapping)框架如Hibernate中,如何优雅地将这些继承关系映射到关系型数据库中,成为了一个重要的议题。本文将深入探讨Hibernate如何处理继承多态映射关系,主要通过三种不同的策略来实现这一...