深入理解对象关系映射
立即解锁
发布时间: 2025-08-19 02:01:31 阅读量: 2 订阅数: 11 


Java持久化实战:JPA深入解析
### 深入理解对象关系映射
#### 1. 基本概念
在对象关系映射中,为了避免频繁区分字段(fields)和属性(properties),我们统一将它们称为属性(attributes)。属性可以是类的字段或属性,后续我们将使用“属性”这一概念。
#### 2. 列映射
- **@Basic 注解**:可视为一个逻辑指示,表明给定的属性是持久化的。若没有该注解,也会有默认的基本映射。
- **@Column 注解**:是与基本映射配套的物理注解,用于指定对象模型不太关注的物理数据库列的特定特征。其中,`name` 元素较为重要,它是一个字符串,用于指定属性映射到的列名,可覆盖默认列名。
以下是一个将属性映射到列的示例:
```java
@Entity
public class Employee {
@Id
@Column(name="EMP_ID")
private long id;
private String name;
@Column(name="SAL")
private long salary;
@Column(name="COMM")
private String comments;
// ...
}
```
该实体对应的表结构如下:
| 表名 | 主键 | 列名 |
| ---- | ---- | ---- |
| EMPLOYEE | EMP_ID | EMP_ID, NAME, SAL, COMM |
在这个示例中,由于类上没有 `@Table` 注解,所以默认表名为 `EMPLOYEE`。`id` 字段通过 `@Column` 注解映射到 `EMP_ID` 列,而非默认的 `ID` 列;`name` 字段未使用 `@Column` 注解,将使用默认列名 `NAME`;`salary` 和 `comments` 字段分别映射到 `SAL` 和 `COMM` 列。
#### 3. 懒加载
当预先知道实体的某些部分很少被访问时,可以采用懒加载来优化实体检索性能。懒加载也被称为延迟加载、按需获取等,意味着对象从数据库初始读取时,某些数据可能不会立即加载,只有在引用或访问时才会获取。
基本映射的获取类型可以通过在 `@Basic` 注解中指定 `fetch` 元素来配置为懒加载或立即加载。`FetchType` 枚举类型定义了该元素的值,包括 `EAGER`(立即加载)和 `LAZY`(懒加载)。将基本映射的获取类型设置为 `LAZY` 意味着提供者可能会延迟加载该属性的状态,直到它被引用。默认情况下,所有基本映射都是立即加载的。
以下是一个将基本映射覆盖为懒加载的示例:
```java
@Entity
public class Employee {
// ...
@Basic(fetch=FetchType.LAZY)
@Column(name="COMM")
private String comments;
// ...
}
```
在这个示例中,假设应用程序很少访问员工记录中的注释,因此将其标记为懒加载。需要注意的是,在这种情况下,`@Basic` 注解不仅用于文档目的,还用于指定字段的获取类型。将 `comments` 字段配置为懒加载后,查询返回的 `Employee` 实例的 `comments` 字段可能为空。应用程序无需进行特殊操作,只需访问 `comments` 字段,若该字段尚未加载,提供者将透明地读取并填充它。
不过,在使用懒加载时,有几点需要注意:
- 懒加载属性的指令只是给持久化提供者的一个提示,提供者不一定会遵循该请求,因为即使提供者提前加载属性,实体的行为也不会受到影响。但指定属性为立即加载可能对实体从持久化上下文分离后访问实体状态至关重要。
- 对于简单类型,懒加载通常不是一个好主意,除非表中有很多列(如数十或数百列)或列很大(如非常大的字符串或字节串)。否则,大多数情况下,懒加载对象属性的子集可能比立即加载更昂贵。
#### 4. 大对象
数据库中,字符或字节为基础的大对象(可达千兆字节范围)通常被称为大对象(LOB)。存储这类大对象的数据库列需要特殊的 JDBC 调用才能从 Java 访问。为了告知提供者在与 JDBC 驱动传递和检索数据时使用 LOB 方法,需要在基本映射中添加 `@Lob` 注解。
LOB 分为两种类型:
- **CLOB(字符大对象)**:存储大字符序列,Java 中的 `char[]`、`Character[]` 和 `String` 对象会映射到 CLOB 列。
- **BLOB(二进制大对象)**:存储大字节序列,Java 中的 `byte[]`、`Byte[]` 和可序列化类型会映射到 BLOB 列。
以下是一个将图像映射到 BLOB 列的示例:
```java
@Entity
public class Employee {
@Id
private long id;
@Basic(fetch=FetchType.LAZY)
@Lob @Column(name="PIC")
private byte[] picture;
// ...
}
```
在这个示例中,`PIC` 列被假定为 BLOB 列,用于存储员工的图片。同时,将该字段标记为懒加载,这是处理不常引用的 LOB 的常见做法。
#### 5. 枚举类型
枚举类型的值是常量,根据应用需求可以有不同的处理方式。在 Java 中,枚举类型的值有一个隐式的序数分配,由它们的声明顺序决定,这个序数在运行时不能修改,可用于在数据库中表示和存储枚举类型的值。默认情况下,提供者会将枚举类型映射为整数类型的数据库列。
以下是一个枚举类型的示例:
```java
public enum EmployeeType {
FULL_TIME_EMPLOYEE,
PART_TIME_EMPLOYEE,
CONTRACT_EMPLOYEE
}
```
在编译时,`FULL_TIME_EMPLOYEE` 的序数为 0,`PART_TIME_EMPLOYEE` 为 1,`CONTRACT_EMPLOYEE` 为 2。以下是将该枚举类型映射到实体的示例:
```java
@Entity
public class Employee {
@Id private long id;
private EmployeeType type;
// ...
}
```
在这个示例中,`type` 字段将映射
0
0
复制全文
相关推荐










