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继承关系映射和java反射机制的运用
Hibernate继承关系映射.pdf 简单明了
用Hibernate映射继承关系
这种映射方式只需为继承关系树的Employee根类创建一张表EMPLOYEES。如图14-4所示,在EMPLOYEES表中不仅提供和Employee类的属性对应的字段,还要提供和它的两个子类的所有属型对应的字段,此外,EMPLOYEES表中需要...
hibernate实现继承关系映射的方式有三种,这种方式是将每个类都映射成一张表。
博文链接:https://shaqiang32.iteye.com/blog/201319
Hibernate一对一数据关联 Hibernate下的多对多关系 Hibernate关系映射 Hibernate继承关系映射 Hibernate映射类型-主键生成器-核心API Hibernate3 插件Eclipse配置
那么,这种继承关系在hibernate是如何映射呢? 对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念。hibernate的集成映射可以理解为持久化类之间的继承关系。在上边的例子中,学生集成了人,可以认为...
对于hibernate的9中对应关系的代码详解和继承关系数据库表结构设计
从多种情况介绍Hibernate的继承多态映射关系
NULL 博文链接:https://zhouxianglh.iteye.com/blog/567708
对于继承关系类的映射。比如在论坛中文章(Ariticla)有主题类型(Topic),有回复类型(Reply)。其中Topic都id、title、context、postDate、type(类型:如普通、精华、置顶......),而Replay有id,title,context,...
NULL 博文链接:https://prowl.iteye.com/blog/519618
Hibernate中的继承关系的映射实现
NULL 博文链接:https://dreamzhong.iteye.com/blog/1203023
主要介绍了Java的Hibernate框架中的继承关系设计,Hibernate是Java的SSH三大web开发框架之一,需要的朋友可以参考下
HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...
{2.2}继承}{48}{section.2.2} {2.2.1}super(), this()}{49}{subsection.2.2.1} {2.2.2}方法重写/覆盖}{50}{subsection.2.2.2} {2.3}修饰符}{51}{section.2.3} {2.4}父类对象的方法调用}{51}{section.2.4} {...
Company与Employee类之间为一对多多态关联关系,如果继承关系树的根类对应一个表,或者每个类对应一个表,那么就能映射Company类的employees集合。本节介绍如何映射多对一多态关联。如图14-11所示,ClassD与ClassA为...