定义 JPA 实体

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;
    
    @Transient
    private 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;
    
    @Transient
    private 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;
    
    @Transient
    private 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上找到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值