Hibernate学习(3) (继承映射,配置文件和注解版)
来源:互联网 发布:ubuntu 字体路径 编辑:程序博客网 时间:2024/06/08 07:13
这篇blog准备写怎样在Hibernate中反应内存对象之间的继承关系.我们知道,内存对象之间是可以有继承关系的,但是在数据库中,我们继承神马的都是浮云,不存在的.那么怎么办呢?Hibernate提供了继承关系映射!(其实就是帮你把原来的一个类以一种特定的方式存储在数据库中.)
我们以官方的例子为例:
分为四种方式:
1. MappedSuperclass
被继承的表在数据库中不映射.
@MappedSuperclasspublic static class Account { @Id private Long id; private String owner; private BigDecimal balance; private BigDecimal interestRate; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } public BigDecimal getInterestRate() { return interestRate; } public void setInterestRate(BigDecimal interestRate) { this.interestRate = interestRate; }}@Entity(name = "DebitAccount")public static class DebitAccount extends Account { private BigDecimal overdraftFee; public BigDecimal getOverdraftFee() { return overdraftFee; } public void setOverdraftFee(BigDecimal overdraftFee) { this.overdraftFee = overdraftFee; }}@Entity(name = "CreditAccount")public static class CreditAccount extends Account { private BigDecimal creditLimit; public BigDecimal getCreditLimit() { return creditLimit; } public void setCreditLimit(BigDecimal creditLimit) { this.creditLimit = creditLimit; }}
CREATE TABLE DebitAccount ( id BIGINT NOT NULL , balance NUMERIC(19, 2) , interestRate NUMERIC(19, 2) , owner VARCHAR(255) , overdraftFee NUMERIC(19, 2) , PRIMARY KEY ( id ))CREATE TABLE CreditAccount ( id BIGINT NOT NULL , balance NUMERIC(19, 2) , interestRate NUMERIC(19, 2) , owner VARCHAR(255) , creditLimit NUMERIC(19, 2) , PRIMARY KEY ( id ))
没有创建Acount表,但是Account的属性在每个子类的数据库表中都存在.
2. Single table
单表映射,所有的类映射到数据库中的一个表
Annotation版本:
@Entity(name = "Account")@Inheritance(strategy = InheritanceType.SINGLE_TABLE)public static class Account { @Id private Long id; private String owner; private BigDecimal balance; private BigDecimal interestRate; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } public BigDecimal getInterestRate() { return interestRate; } public void setInterestRate(BigDecimal interestRate) { this.interestRate = interestRate; }}@Entity(name = "DebitAccount")public static class DebitAccount extends Account { private BigDecimal overdraftFee; public BigDecimal getOverdraftFee() { return overdraftFee; } public void setOverdraftFee(BigDecimal overdraftFee) { this.overdraftFee = overdraftFee; }}@Entity(name = "CreditAccount")public static class CreditAccount extends Account { private BigDecimal creditLimit; public BigDecimal getCreditLimit() { return creditLimit; } public void setCreditLimit(BigDecimal creditLimit) { this.creditLimit = creditLimit; }}
CREATE TABLE Account ( DTYPE VARCHAR(31) NOT NULL , id BIGINT NOT NULL , balance NUMERIC(19, 2) , interestRate NUMERIC(19, 2) , owner VARCHAR(255) , overdraftFee NUMERIC(19, 2) , creditLimit NUMERIC(19, 2) , PRIMARY KEY ( id ))
Account Table:
Single table版本,需要在Account表格中添加所有子类可能的属性以及对于类的描述性列(,因为子父类都在一个表中,我们需要知道一个元组是什么类,所以必须有一个描述列更多关于描述列,这里DTYPE即是它的描述性列,只能为String,Char,INTEGER),因此会有大量的数据冗余.
注解版本使用另外三个类:
Plane(父类),Airbus(子类),Boeing(子类)
public class Plane { private Long id; private String type; private String manufacturer; public Plane() {} public Long getId() { return id; } private void setId(Long id) { this.id = id; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; }}public class Airbus extends Plane{ private String capacity; public Airbus() {} public String getCapacity() { return capacity; } private void setCapacity(String capacity) { this.capacity = capacity; }}public class Boeing extends Plane{ private String comfort; public Boeing() {} public String getComfort() { return comfort; } private void setComfort(String comfort) { this.comfort = comfort; }}
配置文件:
<hibernate-mapping package="Sample.Entity"discriminator-value="0“ > <class name="Plane" table="planes"> <id name="id" column="ID"> <generator class="native"/> </id> <discriminator column="DISC" type="string"/> <property name="type"/> <property name="manufacturer"/> <subclass name="Airbus" discriminator-value="1"> <property name="capacity" /> </subclass> <subclass name="Boeing" discriminator-value="2"> <property name="comfort" /> </subclass> </class></hibernate-mapping>
优点:效率最高,不需要多表联合查询.
缺点:会产生太多的数据冗余,大量的null字段,导致完整性约束不能在数据库层面上使用,只能依靠数据操作层维持.
3. Joined table
@Entity(name = "Account")@Inheritance(strategy = InheritanceType.JOINED)public static class Account { @Id private Long id; private String owner; private BigDecimal balance; private BigDecimal interestRate; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } public BigDecimal getInterestRate() { return interestRate; } public void setInterestRate(BigDecimal interestRate) { this.interestRate = interestRate; }}@Entity(name = "DebitAccount")public static class DebitAccount extends Account { private BigDecimal overdraftFee; public BigDecimal getOverdraftFee() { return overdraftFee; } public void setOverdraftFee(BigDecimal overdraftFee) { this.overdraftFee = overdraftFee; }}@Entity(name = "CreditAccount")public static class CreditAccount extends Account { private BigDecimal creditLimit; public BigDecimal getCreditLimit() { return creditLimit; } public void setCreditLimit(BigDecimal creditLimit) { this.creditLimit = creditLimit; }}
CREATE TABLE Account ( id BIGINT NOT NULL , balance NUMERIC(19, 2) , interestRate NUMERIC(19, 2) , owner VARCHAR(255) , PRIMARY KEY ( id ))CREATE TABLE CreditAccount ( creditLimit NUMERIC(19, 2) , id BIGINT NOT NULL , PRIMARY KEY ( id ))CREATE TABLE DebitAccount ( overdraftFee NUMERIC(19, 2) , id BIGINT NOT NULL , PRIMARY KEY ( id ))ALTER TABLE CreditAccountADD CONSTRAINT FKihw8h3j1k0w31cnyu7jcl7n7nFOREIGN KEY (id) REFERENCES AccountALTER TABLE DebitAccountADD CONSTRAINT FKia914478noepymc468kiaivqmFOREIGN KEY (id) REFERENCES Account
创建了三个表格,子表中只存在子类的自身属性加上父类的外键约束.
因为在查询的时候,语句大约是:
select ... from Account ... Join DebitAccount ... Join CreditAccount.
这种策略使用join 操作父子类表.
配置文件版本:
public class Cat { private Long uid; private Date birthday; private String color; private String sex; private int weight; public Cat() { } public Long getUid() { return uid; } private void setUid(Long uid) { this.uid = uid; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; }}
public class DomesticCat extends Cat { private String name; public DomesticCat() { } public String getName() { return name; } public void setName(String name) { this.name = name; }}
<hibernate-mapping package="Sample.Entity"><class name="Cat" table="CATS"> <id name="uid" column="UID"> <generator class="native"/> </id> <property name="birthday" type="date"/> <property name="color"/> <property name="sex"/> <property name="weight"/> <joined-subclass name="DomesticCat" table="DOMESTIC_CATS"> <key column="CAT"/> <property name="name" type="string"/> </joined-subclass></class></hibernate-mapping>
映射到多张表中,但是子表并没有父表的属性,只有一个父表的外键.
优点:减少了数据冗余
缺点:数据量太大是,join操作会影响性能
4. Table per class
每个表一个映射表,注意:此时ID生成策略不能使用generate,需要手动保证子父表之间ID的唯一性,可以考虑使用generateTable方法.
@Entity(name = "Account")@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)public static class Account { @Id private Long id; private String owner; private BigDecimal balance; private BigDecimal interestRate; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public BigDecimal getBalance() { return balance; } public void setBalance(BigDecimal balance) { this.balance = balance; } public BigDecimal getInterestRate() { return interestRate; } public void setInterestRate(BigDecimal interestRate) { this.interestRate = interestRate; }}@Entity(name = "DebitAccount")public static class DebitAccount extends Account { private BigDecimal overdraftFee; public BigDecimal getOverdraftFee() { return overdraftFee; } public void setOverdraftFee(BigDecimal overdraftFee) { this.overdraftFee = overdraftFee; }}@Entity(name = "CreditAccount")public static class CreditAccount extends Account { private BigDecimal creditLimit; public BigDecimal getCreditLimit() { return creditLimit; } public void setCreditLimit(BigDecimal creditLimit) { this.creditLimit = creditLimit; }}
CREATE TABLE Account ( id BIGINT NOT NULL , balance NUMERIC(19, 2) , interestRate NUMERIC(19, 2) , owner VARCHAR(255) , PRIMARY KEY ( id ))CREATE TABLE CreditAccount ( id BIGINT NOT NULL , balance NUMERIC(19, 2) , interestRate NUMERIC(19, 2) , owner VARCHAR(255) , creditLimit NUMERIC(19, 2) , PRIMARY KEY ( id ))CREATE TABLE DebitAccount ( id BIGINT NOT NULL , balance NUMERIC(19, 2) , interestRate NUMERIC(19, 2) , owner VARCHAR(255) , overdraftFee NUMERIC(19, 2) , PRIMARY KEY ( id ))
注意生成了三张表,对应三个类,并且每个类的主键都没有依赖,为了保证每个对象都是有唯一的id,(内存中三个对象id都需要不同)我们需要手动保证三个table的id列都是唯一的,比如说,Account中有一个元组中id为1,那么DebitAccount中就不能有元组id为1.同理,DebitAccount中有id为1,其他两个表也是一样.
查询的时候,三个表之间使用了union查询语句.
配置版本:
public class Fruit { private Long id; private String shape; private String flavor; private String color; public Fruit() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getShape() { return shape; } public void setShape(String shape) { this.shape = shape; } public String getFlavor() { return flavor; } public void setFlavor(String flavor) { this.flavor = flavor; } public String getColor() { return color; } public void setColor(String color) { this.color = color; }}public class Banana extends Fruit{ private int length; public Banana() { } public int getLength() { return length; } public void setLength(int length) { this.length = length; }}public class Apple extends Fruit { private int weight; public Apple() { } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; }}
<hibernate-mapping package="entities"> <class name="entities.Fruit" table="`fruit`"> <id name="id" column="ID"> <!--table per class 策略不能使用 generate 策略,否则无法生成sessionFactory.可以考虑使用generateTable--> </id> <property name="shape"/> <property name="flavor"/> <property name="color"/> <union-subclass name="Apple" table="`apple`"> <property name="weight"/> </union-subclass> <union-subclass name="entities.Banana" table="`banana`"> <property name="length"/> </union-subclass> </class></hibernate-mapping>
好了,至此,内存中的对象与数据库元组之间的继承关系和关联关系已经下完了.
贴上课上PPT
- Hibernate学习(3) (继承映射,配置文件和注解版)
- Hibernate继承映射学习
- Hibernate 映射和继承
- Hibernate学习-10-组件映射和继承映射
- Hibernate使用注解,继承映射写法
- 【Hibernate框架学习】:Hibernate进阶之详解Hibernate配置文件和对象关系映射配置文件
- Hibernate学习_016_继承映射
- hibernate学习之继承映射
- Hibernate学习之---继承映射
- hibernate配置文件和映射文件
- Hibernate继承映射和一对一映射
- hibernate组件映射和继承映射
- Hibernate4学习总结(3)--注解形式的基础映射,主键映射,基本属性映射,复合属性映射,继承映射。
- Hibernate学习笔记 3 - 关系映射配置(基于注解)
- hibernate注解版关联映射
- hibernate注解版关联映射
- 学习之路-Hibernate注解映射
- Hibernate学习---第三节:映射配置文件详解
- 判断是否是合法的出栈序列
- 勒索病毒刷出的存在感远不及安全公司强!
- JAVA 类加载时机与过程
- codeforce811b Vladik and Complicated Book(都是不好好想题惹的祸)
- static关键字
- Hibernate学习(3) (继承映射,配置文件和注解版)
- 数据库连接池
- [杂题 背包DP] Codeforces 793E Tinkoff Challenge
- Eclipse使用笔记
- OpenMP
- C# winform 初学者各种问题集合(已经本人验证能有效解决问题)
- Makefile的编写等
- 全球顶级15个技术类博客
- Django Error: No module named XXX