定义 JPA 实体
admin
2024-03-23 15:03:02

1. 简介

在本教程中,我们将了解实体的基础知识,以及在 JPA 中定义和自定义实体的各种注释。

2. 实体

JPA 中的实体只不过是表示可以持久保存到数据库的数据的 POJO。实体表示存储在数据库中的表。实体的每个实例都表示表中的一行。

2.1. 实体注释

假设我们有一个名为 Student 的 POJO,它表示学生的数据我们希望将其存储在数据库中:

public class Student {// fields, getters and setters}

为了做到这一点,我们应该定义一个实体,以便JPA知道它。

因此,让我们通过使用@Entity注释来定义它。我们必须在类级别指定此注释。我们还必须确保实体具有 no-arg 构造函数和主键:

@Entity
public class Student {// fields, getters and setters}

实体名称默认为类的名称。我们可以使用 name 元素更改它的名称:

@Entity(name="student")
public class Student {// fields, getters and setters}

因为各种 JPA 实现会尝试对我们的实体进行子类化以提供它们的功能,所以实体类不能被声明为 final

2.2. ID 注释

每个 JPA 实体都必须有一个唯一标识它的主键。@Id注释定义主键。我们可以通过不同的方式生成标识符,这些标识符由@GeneratedValue注释指定。

我们可以从四种带有策略元素的 id 生成策略中进行选择。该值可以是自动、表、序列标识:

@Entity
public class Student {@Id@GeneratedValue(strategy=GenerationType.AUTO)private Long id;private String name;// getters and setters
}

如果我们指定生成类型AUTO,JPA 提供程序将使用它想要生成标识符的任何策略。

如果我们注释实体的字段,JPA 提供程序将使用这些字段来获取和设置实体的状态。除了字段访问之外,我们还可以进行属性访问或混合访问,这使我们能够在同一实体中同时使用字段和属性访问

2.3. 表格注释

在大多数情况下,数据库中表的名称和实体的名称不会相同。

在这些情况下,我们可以使用@Table注释指定表名:

@Entity
@Table(name="STUDENT")
public class Student {// fields, getters and setters}

我们还可以使用架构元素提及架构

@Entity
@Table(name="STUDENT", schema="SCHOOL")
public class Student {// fields, getters and setters}

架构名称有助于将一组表与另一组表区分开来。

如果我们不使用@Table注释,则表的名称将是实体的名称。

2.4. 列注释

就像@Table注释一样,我们可以使用@Column注释来提及表中列的详细信息。

@Column注释具有许多元素,例如名称、长度、可为空和唯一

@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
}

name 元素指定表中列的名称。长度元素指定其长度。可为空元素指定列是否可为空,唯一元素指定列是否唯一

如果我们不指定此注释,则表中列的名称将是字段的名称。

2.5. 瞬态注释

有时,我们可能希望使字段非持久性。 我们可以使用@Transient注释来做到这一点。它指定不会保留该字段。

例如,我们可以从出生之日起计算学生的年龄。

因此,让我们用@Transient注释来注释字段年龄

@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;@Transientprivate Integer age;// other fields, getters and setters
}

因此,字段年龄不会保留到表中。

2.6. 时间标注

在某些情况下,我们可能必须在表中保存时态值。

为此,我们有@Temporal注释:

@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;@Transientprivate Integer age;@Temporal(TemporalType.DATE)private Date birthDate;// other fields, getters and setters
}

但是,在JPA 2.2中,我们还支持java.time.LocalDate,java.time.LocalTime,java.time.LocalDateTime,java.time.OffsetTime和java.time.OffsetDateTime

2.7. 枚举注释

有时,我们可能希望持久化 Java 枚举类型。

我们可以使用@Enumerated注释来指定枚举是按名称还是按序号(默认)持久化:

public enum Gender {MALE, FEMALE
}
@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;@Transientprivate Integer age;@Temporal(TemporalType.DATE)private Date birthDate;@Enumerated(EnumType.STRING)private Gender gender;// other fields, getters and setters
}

实际上,如果我们要按枚举的序数保留性别,我们根本不需要指定@Enumerated注释。

但是,为了保留按枚举名称划分的性别,我们使用 EnumType.STRING 配置了注释。

3. 结论

在本文中,我们学习了什么是 JPA 实体以及如何创建它们。我们还了解了可用于进一步自定义实体的不同注释。

本文的完整代码可以在Github上找到。

相关内容

热门资讯

腐竹炖白菜想要好吃,记住这个诀... "这腐竹怎么炖得比肉还香?"上周去姑姑家吃饭,看着她端上桌的那盆油亮亮的腐竹炖白菜,我忍不住发出了这...
养生操、日间徒步、非遗晚宴、睡... 慢生活治愈系经营体验真人秀《亲爱的·客栈2026》,今晚推出“东坡养生日”特辑,将传统文化、健康生活...
一口就上头!云南人把吃“玩”明... 在云南,“绿的都是菜,会动的都是肉”,春食花、夏食菌、秋食果、冬食菜,三餐四季味不同。鲜糯的河苔炒饭...
在贵安“村咖”,找到“对味”的... 都说城市咖啡“卷”疯了?那你可能没来过贵州的乡村。这里的咖啡,长在梧桐树下,种在试验田里,甚至藏在一...