1. 简介
本文将带你了解 JPA 中实体的基本概念,以及常用的注解及其作用。这些注解可以帮助我们定义和定制实体类,使其与数据库表结构一一对应。
2. 实体(Entity)
在 JPA 中,实体本质上就是普通的 Java 对象(POJO),用于表示可以被持久化到数据库的数据。每个实体类对应一张数据库表,实体类的实例则对应表中的一行记录。
2.1 @Entity
注解
假设我们有一个表示学生信息的 POJO 类 Student
,我们希望将其映射为数据库实体:
public class Student {
// fields, getters and setters
}
为了让 JPA 能识别这个类为实体,我们需要使用 @Entity
注解:
@Entity
public class Student {
// fields, getters and setters
}
默认情况下,实体名与类名相同。我们也可以通过 name
属性自定义实体名:
@Entity(name = "student")
public class Student {
// fields, getters and setters
}
⚠️注意:JPA 实现框架(如 Hibernate)可能会对实体类进行子类化,因此实体类不能是 final 的。
2.2 @Id
与 @GeneratedValue
注解
每个 JPA 实体必须有一个主键来唯一标识该实体。我们使用 @Id
注解来定义主键字段。主键值可以由数据库自动生成,也可以手动设置。使用 @GeneratedValue
可以指定主键的生成策略。
JPA 支持以下四种主键生成策略:
AUTO
:由 JPA 提供者自动选择TABLE
:使用数据库表模拟序列SEQUENCE
:使用数据库序列IDENTITY
:依赖数据库自增列
示例代码如下:
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
// getters and setters
}
⚠️注意:主键字段不能是 final 的,且实体类必须有无参构造函数。
2.3 @Table
注解
通常,数据库表名和实体类名并不一致。此时可以使用 @Table
注解来指定表名:
@Entity
@Table(name = "STUDENT")
public class Student {
// fields, getters and setters
}
还可以通过 schema
属性指定数据库模式(schema):
@Entity
@Table(name = "STUDENT", schema = "SCHOOL")
public class Student {
// fields, getters and setters
}
✅建议:在多模块或复杂项目中,使用 schema 可以更清晰地组织数据库结构。
2.4 @Column
注解
@Column
注解用于定义实体字段与数据库列之间的映射关系。它支持多个属性,如:
name
:列名length
:长度nullable
:是否允许为空unique
:是否唯一
示例:
@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "STUDENT_NAME", length = 50, nullable = false, unique = false)
private String name;
// other fields, getters and setters
}
如果没有使用 @Column
,默认字段名将与数据库列名一致。
2.5 @Transient
注解
有时我们希望某个字段不被持久化到数据库中,这时可以使用 @Transient
注解。
例如,age
字段可能由 birthDate
推导而来,不需要保存在数据库中:
@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "STUDENT_NAME", length = 50, nullable = false)
private String name;
@Transient
private Integer age;
// other fields, getters and setters
}
✅踩坑提醒:不要在 @Transient
字段上使用 @Column
,否则会导致持久化异常。
2.6 @Temporal
注解
当字段是 java.util.Date
或 java.util.Calendar
类型时,需要使用 @Temporal
注解来指定时间精度类型:
@Temporal(TemporalType.DATE)
private Date birthDate;
支持的类型包括:
DATE
:仅日期(yyyy-MM-dd)TIME
:仅时间(HH:mm:ss)TIMESTAMP
:日期+时间(yyyy-MM-dd HH:mm:ss)
⚠️注意:从 JPA 3.1 开始,推荐使用 java.time.LocalDate
、LocalDateTime
等新时间 API,无需再使用 @Temporal
。
2.7 @Enumerated
注解
如果实体字段是 Java 枚举类型,可以使用 @Enumerated
注解指定其存储方式:
public enum Gender {
MALE, FEMALE
}
@Enumerated(EnumType.STRING)
private Gender gender;
支持的存储方式:
EnumType.ORDINAL
:按枚举顺序存储为整数(默认)EnumType.STRING
:按枚举名称存储为字符串
✅建议:使用 EnumType.STRING
更直观,避免因枚举顺序变化导致数据错误。
3. 小结
本篇文章详细介绍了 JPA 实体的基本概念和常用注解,包括:
注解 | 用途 |
---|---|
@Entity |
标记一个类为 JPA 实体 |
@Id |
定义主键 |
@GeneratedValue |
指定主键生成策略 |
@Table |
映射实体类与数据库表 |
@Column |
定义字段与数据库列的映射 |
@Transient |
标记非持久化字段 |
@Temporal |
处理日期时间类型字段 |
@Enumerated |
持久化枚举类型字段 |
掌握这些注解是使用 JPA 的基础,也是构建高质量数据访问层的关键。