JPA的介绍分析

  • Java持久化API (JPA) 显著简化了Java Bean的持久性并提供了一个对象关系映射方法,该方法使您可以采用声明方式定义如何通过一种标准的可移植方式,将Java 对象映射到关系数据库表以及后续的一系列数据持久化行为。

  • JPA可以将任何普通的Java 对象 (POJO) 类指定为 JPA 实体。

    • JPA实体:一个应使用JPA实现程序的服务将其非临时字段持久保存到关系数据库(在 Java EE EJB 容器的内部或在简单 Java SE 应用程序中的 EJB 容器的外部)的 Java 对象。
    • 可以使用注解配置实体的JPA行为,注解是一种使用元数据修饰 Java 源代码的简单表达方法,它编译为相应的 Java 类文件,以便在运行时由 JPA 持久化机制提供程序解释以管理 JPA 行为。
  • 例如,要将Java类指定为JPA实体,请使用@Entity注解:

JPA注解总览




JPA实体型注解

@Entity

使用 @Entity 批注将普通的旧式 Java 对象 (POJO) 类指定为实体,并使其可用于 JPA 服务。必须将 POJO 类指定为实体,然后才可以使用任何其他 JPA 批注。

@Table

默认情况下,JPA持续性提供程序假设实体的所有持久字段均存储到一个名称为实体名称的数据库表中(请参阅 @Entity )。 在以下条件下,使用 @Table注解可以指定与实体关联的主表:

实体名称难于处理、是一个保留字、与预先存在的数据模型不兼容或作为数据库中的表名无效需要控制表所属的目录或模式。

如果希望 JPA 将某些字段持久保存到主表,而将其他字段持久保存到一个或多个辅助表,请参阅@SecondaryTable 。 下表列出了此批注的属性。有关更多详细信息,请参阅 API 。

@Entity
@Table(name="Model")
public class JavaModel implements Serializable {
...
}

@TableGenerator

  • 如果使用 @GeneratedValue 批注指定一个 TABLE 类型的主键生成器,可以使用 @TableGenerator 批注微调该主键生成器以:

    • 由于名称难于处理、是一个保留字、与预先存在的数据模型不兼容或作为数据库中的表名无效而更改主键生成器的表名称
    • 更改分配大小以匹配应用程序要求或数据库性能参数
    • 更改初始值以匹配现有的数据模型(例如,如果基于已经为其分配或保留了一组主键值的现有数据集构建)
    • 使用特定目录或模式配置主键生成器的表
    • 在主键生成器表的一列或多列商配置一个唯一的约束
@TableGenerator 属性



显示了如何使用此注解为名为 empGen 的 TABLE 主键生成器指定分配大小。

@TableGenerator
@Entity
public class Employee implements Serializable {  
@Id
@TableGenerator(
name="empGen",
allocationSize=1
)
@GeneratedValue(strategy=TABLE, generator="empGen")
@Column(name="CUST_ID")
public Long getId() {
return id;
    }
    ...

@Temporal

使用 @Temporal 注解指定 JPA 的提供程序应只为 java.util.Date 和 java.util.Calendar 类型的字段或属性持久保存的数据库类型,可以与 @Basic 一起使用。

示例,显示了如何使用此批注指定 JPA 持续性提供程序应将 java.util.Date 字段 startDate 持久保存为 DATE ( java.sql.Date ) 数据库类型。

@Entity
public class Employee {
@Temporal(DATE)
protected java.util.Date startDate;
    ...
}

@Transient

  • 默认情况下,JPA 持久化提供程序假设实体的所有字段均为持久字段。
  • 使用 @Transient 注解指定实体的非持久字段或属性,例如,一个在运行时使用但并非实体状态一部分的字段或属性。
  • JPA 提供程序不会对批注为 @Transient 的属性或字段持久保存(或创建数据库模式)。
  • 该注解可以与 @Entity 、@MappedSuperclass 和 @Embeddable 一起使用。
  • 该注解没有属性。
@Entity
public class Employee {   
@Id
int id;   
@Transient
Session currentSession;   
...}

@Column

默认情况下,JPA 持续性提供程序假设每个实体的持久字段存储在其名称与持久字段的名称相匹配的数据库表列中。

使用 @Column 批注:

将持久字段与其他名称关联(如果默认列名难于处理、与事先存在的数据模型不兼容或作为数据库中的列名无效)

将持久字段与辅助表中的列关联(请参阅 @SecondaryTable )

微调数据库中列的特征

@Column 属性





如何使用此批注使 JPA 将 empId 持久保存到辅助表 EMP_HR 中的列 EMP_NUM 。默认情况下,JPA 将 empName 持久保存到主表 Employee 中的列 empName 。

@Column

@Entity
@SecondaryTable(name="EMP_HR")
public class Employee implements Serializable {   @Column(name="EMP_NUM", table="EMP_HR")
private Long empId;
private String empName;
}

@UniqueConstraint

默认情况下,JPA持久化提供程序假设所有列均可以包含重复值。

使用@UniqueConstraint注解指定将在为主表或辅助表生成的DDL中包含一个唯一约束,或者,您可以在列级别指定唯一约束。

属性状态

显示了如何使用此注解对主表 EMP 中的列 EMP_ID 和 EMP_NAME 指定一个唯一约束,使用唯一约束的 @Table。

@Entity
@Table(
name="EMP",
uniqueConstraints={@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})}
)
public class Employee implements Serializable {
    ...
}

@Version

默认情况下,JPA持久化提供程序假设应用程序负责数据一致性。

使用@Version注解通过指定用作其乐观锁定值的实体类的版本字段或属性来启用 JPA 管理的乐观锁定(推荐做法)。

  • 选择版本字段或属性时,确保:

    • 每个实体只有一个版本字段或属性
    • 选择一个持久保存到主表的属性或字段(请参阅 @Table )
    • 您的应用程序不修改版本属性或字段

如何使用此注解将属性getVersionNum指定为乐观锁定值。在该示例中,该属性的列名设置为OPTLOCK(请参阅 @Column ),而非属性的默认列名。

@Version

@Entity
public class Employee implements Serializable {
    ...
@Version
@Column(name="OPTLOCK")
protected int getVersionNum() {
return versionNum;
}
    ...
}

@Embeddable 和 @Embedded

  • 使用 @Embeddable 批注指定一个类,该类的实例存储为拥有实体的固有部分并共享该实体的身份。嵌入对象的每个持久属性或字段都将映射到实体的数据库表。

  • 类 EmploymentPeriod 在用作为 @Embedded 的持久字段的类型时可以嵌套到实体中.

@Embeddable
public class EmploymentPeriod {
java.util.Date startDate;
java.util.Date endDate;
...
}

@Embedded

  • 使用 @Embedded 批注指定一个持久字段,该字段的 @Embeddable 类型可以存储为拥有实体的固有部分,并共享该实体的身份。

  • 嵌入对象的每个持久属性或字段均映射到拥有实体的数据库表。

  • 可以结合使用 @Embedded 和 @Embeddable 以建立严格所有权关系的模型,以便在删除了拥有对象的情况下还将删除被拥有的对象。嵌入的对象不应映射到多个表。

  • @Embeddable 类中指定的列定义适用于 @Embedded 类。

  • 如果要覆盖这些列定义,请使用 @AttributeOverride 。

  • @Embeddable 类 EmploymentPeriod可以使用指定的属性覆盖嵌入到实体类中。

@Entity
public class Employee implements Serializable{...
@Embedded
@AttributeOverrides({
@AttributeOverride(name="startDate", column=@Column("EMP_START")),
@AttributeOverride(name="endDate", column=@Column("EMP_END"))
)
public EmploymentPeriod getEmploymentPeriod() {}}

@EmbeddedId

使用 @EmbeddedId 批注指定一个由实体拥有的可嵌入复合主键类(通常由两个或更多基元类型或 JDK 对象类型组成)。从原有数据库映射时(此时数据库键由多列组成),通常将出现复合主键。

复合主键类具有下列特征:

  • 它是一个普通的旧式 Java 对象 (POJO) 类。
  • 它必须为 public ,并且必须有一个 public 无参数构造函数。
  • 如果使用基于属性的访问,则主键类的属性必须为 public 或 protected 。
  • 它必须是可序列化的。
  • 它必须定义 equals 和 hashCode 方法。
  • 这些方法的值相等性的语义必须与键映射到的数据库类型的数据库相等性一致。
@Embeddable
public class EmployeePK implements Serializable{
private String name;
private long id;
public EmployeePK()  {    }
//setter and getter
public int hashCode() {
return (int) name.hashCode() + id;
}
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof EmployeePK)) return false;
if (obj == null) return false;
EmployeePK pk = (EmployeePK) obj;
return pk.id == id && pk.name.equals(name);
}
} @Entity
public class Employee implements Serializable{
EmployeePK primaryKey;
public Employee(){}
@EmbeddedId
public EmployeePK getPrimaryKey()  {
return primaryKey;
}
public void setPrimaryKey(EmployeePK pk){
primaryKey = pk;
}
...
}

@MappedSuperclass

  • 使用 @MappedSuperclass 批注指定一个实体类从中继承持久字段的超类。当多个实体类共享通用的持久字段或属性时,这将是一个方便的模式。

  • 您可以像对实体那样使用任何直接和关系映射批注(如 @Basic 和 @ManyToMany)对该超类的字段和属性进行批注,但由于没有针对该超类本身的表存在,因此这些映射只适用于它的子类。继承的持久字段或属性属于子类的表。

  • 可以在子类中使用 @AttributeOverride 或 @AssociationOverride 批注来覆盖超类的映射配置。

如何使用此批注将 Employee 指定为映射超类。如何扩展实体中的此超类,以及如何在实体类中使用 @AttributeOverride 以覆盖超类中设置的配置。

@MappedSuperclass
public class Employee {
@Id
protected Integer empId; @Version
protected Integer version; @ManyToOne
@JoinColumn(name="ADDR")
protected Address address; public Integer getEmpId() {
...
} public void setEmpId(Integer id) {
...
} public Address getAddress() {
...
} public void setAddress(Address addr) {
...
}
} @MappedSuperclass
@Entity
@AttributeOverride(name="address", column=@Column(name="ADDR_ID"))
public class PartTimeEmployee extends Employee { @Column(name="WAGE")
protected Float hourlyWage; public PartTimeEmployee() {
...
} public Float getHourlyWage() {
...
} public void setHourlyWage(Float wage) {
...
}
}

@EntityListeners

@EntityListeners将一个或多个实体监听程序类与 @Entity 或 @MappedSuperclass 关联,条件是您需要在指定的生命周期事件发生时执行逻辑。

  • 不希望在实体 API 中公开生命周期监听程序方法。
  • 要在不同的实体类型之间共享生命周期监听程序逻辑。
  • 当实体或子类上发生生命周期事件时,JPA 持续性提供程序将按监听程序定义的顺序通知每个实体监听程序,并调用使用相应的生命周期事件类型进行批注的实体监听程序方法(如果有)。

实体监听程序类具有以下特征:

  • 它是一个普通的旧式 Java 对象 (POJO) 类
  • 它有一个或多个具有以下签名的回调方法:
  • public void (Object)
  • 可以指定参数类型 Object ,或实体监听程序将与其关联的实体类的类型。
  • 它用一个或多个生命周期事件批注对每个回调方法进行批注。
  • 一个生命周期事件只能与一个回调监听程序方法关联,但某个给定的回调监听程序方法可以与多个生命周期事件关联。
  • 如果使用实体监听程序,则可以管理哪些实体监听程序使用

@EntityListeners 属性

显示了您可以将多个生命周期事件与给定的实体监听程序类方法关联,但任何给定的生命周期事件只能在实体监听程序类中出现一次。

@Entity
@EntityListeners(value={EmployeePersistListner.class,
EmployeeRemoveListener.class})
public class Employee implements Serializable {
    ...
} public class EmployeePersistListener {
@PrePersist
public void employee PrePersist(Object employee) {}}; public class EmployeeRemoveListener {
@PreRemove
@PostRemove
public void employeePreRemove(Object employee) { } ...}

@ExcludeDefaultListeners

如果默认监听程序行为不适用,请使用 @ExcludeDefaultListeners 批注覆盖(并阻止)针对给定 @Entity 或 @MappedSuperclass 执行的默认监听程序。

	@Entity
@ExcludeDefaultListeners
public class Employee implements Serializable {
    ...
}

☕【Java技术指南】「JPA编程专题」让你不再对JPA技术中的“持久化型注解”感到陌生了!的更多相关文章

  1. ☕【Java技术指南】「并发编程专题」针对于Guava RateLimiter限流器的入门到精通(含实战开发技巧)

    并发编程的三剑客 在开发高并发系统时有三剑客:缓存.降级和限流. 缓存 缓存的目的是提升系统访问速度和增大系统处理容量. 降级 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题 ...

  2. ☕【Java技术指南】「并发编程专题」Fork/Join框架基本使用和原理探究(基础篇)

    前提概述 Java 7开始引入了一种新的Fork/Join线程池,它可以执行一种特殊的任务:把一个大任务拆成多个小任务并行执行. 我们举个例子:如果要计算一个超大数组的和,最简单的做法是用一个循环在一 ...

  3. ☕【Java技术指南】「并发编程专题」CompletionService框架基本使用和原理探究(基础篇)

    前提概要 在开发过程中在使用多线程进行并行处理一些事情的时候,大部分场景在处理多线程并行执行任务的时候,可以通过List添加Future来获取执行结果,有时候我们是不需要获取任务的执行结果的,方便后面 ...

  4. 🏆【Java技术专区】「并发编程专题」教你如何使用异步神器CompletableFuture

    前提概要 在java8以前,我们使用java的多线程编程,一般是通过Runnable中的run方法来完成,这种方式,有个很明显的缺点,就是,没有返回值.这时候,大家可能会去尝试使用Callable中的 ...

  5. ☕【Java技术指南】「并发原理专题」AQS的技术体系之CLH、MCS锁的原理及实现

    背景 SMP(Symmetric Multi-Processor) 对称多处理器结构,它是相对非对称多处理技术而言的.应用十分广泛的并行技术. 在这种架构中,一台计算机由多个CPU组成,并共享内存和其 ...

  6. 🏆【Java技术专区】「探针Agent专题」Java Agent探针的技术介绍(1)

    前提概要 Java调式.热部署.JVM背后的支持者Java Agent: 各个 Java IDE 的调试功能,例如 eclipse.IntelliJ : 热部署功能,例如 JRebel.XRebel. ...

  7. ☕【Java深层系列】「并发编程系列」深入分析和研究MappedByteBuffer的实现原理和开发指南

    前言介绍 在Java编程语言中,操作文件IO的时候,通常采用BufferedReader,BufferedInputStream等带缓冲的IO类处理大文件,不过java nio中引入了一种基于Mapp ...

  8. 🏆【Java技术专区】「开发实战专题」Lombok插件开发实践必知必会操作!

    前言 在目前众多编程语言中,Java 语言的表现还是抢眼,不论是企业级服务端开发,还是 Andorid 客户端开发,都是作为开发语言的首选,甚至在大数据开发领域,Java 语言也能占有一席之地,如Ha ...

  9. 🏆【Java技术专区】「延时队列专题」教你如何使用【精巧好用】的DelayQueue

    延时队列前提 定时关闭空闲连接:服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之. 定时清除额外缓存:缓存中的对象,超过了空闲时间,需要从缓存中移出. 实现任务超时处理:在网络协议滑动窗口请求 ...

随机推荐

  1. CF上部分树形DP练习题

    本次 5 道题均来自Codeforce 关于树形DP的算法讲解:Here 791D. Bear and Tree Jumps 如果小熊每次能跳跃的距离为1,那么问题变为求树上任意两点之间距离之和. 对 ...

  2. 对象 绑定关系 隐藏属性 property 继承

    绑定方法两种: 1.绑定给对象的 class Student(): country = 'CHINA' def __init__(self,name,age): self.name = name se ...

  3. ansible 常用模块总结

    记录常用的模块功能,详细使用查看官网. 1. file模块 创建软连接 ansible test -m file -a "src=/tmp/conf.d dest=/tmp/conf.d s ...

  4. CSS3图片倒影技术

    http://bbs.itheima.com/thread-330315-1-1.html?wymlxt

  5. C# 高级进阶(一)

    产品是怎样开发出来的 首先了解--产品MVP(Minimum Viable Product)的概念 最小可行产品--意思即开发最初应该是根据参品预期,最快构建出一个符合预期可行的功能合集,后期再通过用 ...

  6. Spring整合Quartz分布式定时任务

    概述虽然单个Quartz实例能给予你很好的Job调度能力,但它不能满足典型的企业需求,如可伸缩性.高可靠性满足.假如你需要故障转移的能力并能运行日益增多的 Job,Quartz集群势必成为你应用的一部 ...

  7. C# Fakes

    我们为了测试程序的运行逻辑,需要写单元测试来验证程序的逻辑.有的时候我们的逻辑需要依赖于外界的事物(需要一个文件,eg:数据库),我们不可能在运行单元测试的计算机都创建一个数据库,所以这个时候我们就需 ...

  8. 虚拟机--第一章走进java--(抄书)

    这是本人阅读周志明老师的<深入理解Java虚拟机>第二版抄写的,有很多省略,不适合直接阅读,需要阅读请出门左转淘宝,右转京东,支持周老师(侵权请联系删除) 第一章走近java 世界上并没有 ...

  9. 使用servlet中是否需要考虑线程问题

    package day09; import java.io.IOException; import javax.servlet.ServletException; import javax.servl ...

  10. ProjectEuler 009题

    题目: A Pythagorean triplet is a set of three natural numbers, a b c, for which, a2 + b2 = c2 For exam ...