作为 Java 企业版 5 (Java EE 5) Enterprise Java Bean (EJB) 3.0 规范的组成部分,Java 持续性 API (JPA) 显著简化了 EJB 持续性并提供了一个对象关系映射方法,该方法使您可以采用声明方式定义如何通过一种标准的可移植方式(在 Java EE 5 应用服务器内部以及 Java 标准版 (Java SE) 5 应用程序中的 EJB 容器外部均可使用)将 Java 对象映射到关系数据库表。
在 JPA 之前,Java EE 应用程序将持续类表示为容器管理的实体 bean。使用 JPA,您可以将任何普通的旧式 Java 对象 (POJO) 类指定为 JPA 实体:一个应使用 JPA 持续性提供程序的服务将其非临时字段持久保存到关系数据库(在 Java EE EJB 容器的内部或在简单 Java SE 应用程序中的 EJB 容器的外部)的 Java 对象。
使用 JPA 时,可以使用批注配置实体的 JPA 行为。批注是一种使用元数据修饰 Java 源代码的简单表达方法,它编译为相应的 Java 类文件,以便在运行时由 JPA 持续性提供程序解释以管理 JPA 行为。
例如,要将 Java 类指定为 JPA 实体,请使用 [color=red]@Entity[/color] 批注,如下所示:
@Entity public class Employee implements Serializable { ... }
您可以有选择地使用批注来修饰实体类以覆盖默认值。这称作按异常进行配置 (configuration by exception)。
本参考广泛引用了 [color=red]JSR-220 Enterprise JavaBean 版本 3.0[/color] Java 持续性 API 规范,以按类别汇总批注信息(请参阅[color=red]表 1-1[/color]),并解释了何时以及如何使用这些批注来自定义 JPA 行为,以满足应用程序的需要。
有关详细信息,请参阅:
*
[color=red]批注索引[/color]
*
[color=red] 完整的 JPA 批注 Javadoc[/color]
表 1-1 按类别划分的 JPA 批注
类别 说明 批注
实体
默认情况下,JPA 持续性提供程序假设 Java 类是非持续类,并且仅当使用此批注对其进行修饰的情况下才可用于 JPA 服务。
使用此批注将普通的旧式 Java 对象 (POJO) 类指定为实体,以便可以将它用于 JPA 服务。
要将类用于 JPA 服务,必须将该类指定为 JPA 实体(使用此批注或 orm.xml 文件)。
[color=red]@Entity[/color]
数据库模式属性
默认情况下,JPA 持续性提供程序假设实体名称对应于同名的数据库表,且实体的数据成员名称对应于同名的数据库列。
使用这些批注覆盖此默认行为,并微调对象模型与数据模型之间的关系。
@Table
@SecondaryTable
@SecondaryTables
@Column
@JoinColumn
@JoinColumns
@PrimaryKeyJoinColumn
@PrimaryKeyJoinColumns
@JoinTable
@UniqueConstraint
身份
默认情况下,JPA 持续性提供程序假设每个实体必须至少有一个用作主键的字段或属性。
使用这些批注指定以下项之一:
*
一个 @Id
*
多个 @Id 和一个 @IdClass
*
一个 @EmbeddedId
还可以使用这些批注微调数据库维护实体身份的方式。
@Id
@IdClass
@EmbeddedId
@GeneratedValue
@SequenceGenerator
@TableGenerator
直接映射
默认情况下,JPA 持续性提供程序为大多数 Java 基元类型、基元类型的包装程序以及 enums 自动配置一个 Basic 映射。
使用这些批注微调数据库实现这些映射的方式。
@Basic
@Enumerated
@Temporal
@Lob
@Transient
关系映射
JPA 持续性提供程序要求您显式映射关系。
使用这些批注指定实体关系的类型和特征,以微调数据库实现这些关系的方式。
@OneToOne
@ManyToOne
@OneToMany
@ManyToMany
@MapKey
@OrderBy
组合
默认情况下,JPA 持续性提供程序假设每个实体均映射到它自己的表。
使用这些批注覆盖其他实体拥有的此种实体行为。
@Embeddable
@Embedded
@AttributeOverride
@AttributeOverrides
@AssociationOverride
@AssociationOverrides
继承
默认情况下,JPA 持续性提供程序假设所有持久字段均由一个实体类定义。
如果实体类继承了一个或多个超类中的某些或所有持续字段,则使用这些批注。
@Inheritance
@DiscriminatorColumn
@DiscriminatorValue
@MappedSuperclass
@AssociationOverride
@AssociationOverrides
@AttributeOverride
@AttributeOverrides
锁定
默认情况下,JPA 持续性提供程序假设应用程序负责数据一致性。
使用此批注启用 JPA 管理的乐观锁定(推荐使用)。
@Version
生命周期回调事件
默认情况下,JPA 持续性提供程序处理所有持续性操作。
如果您要在实体生命周期内随时调用自定义逻辑,请使用这些批注将实体方法与 JPA 生命周期事件关联。图 1-1 演示了这些生命周期事件之间的关系。
@PrePersist
@PostPersist
@PreRemove
@PostRemove
@PreUpdate
@PostUpdate
@PostLoad
@EntityListeners
@ExcludeDefaultListeners
@ExcludeSuperclassListeners
实体管理器
在使用 JPA 持续性提供程序的应用程序中,您可以使用 EntityManager 实例执行所有持续性操作(创建、读取、更新和删除)。
使用这些批注将实体与实体管理器关联并自定义实体管理器的环境。
@PersistenceUnit
@PersistenceUnits
@PersistenceContext
@PersistenceContexts
@PersistenceProperty
查询
在使用 JPA 持续性提供程序的应用程序中,可以使用实体管理器动态创建和执行查询,也可以预定义查询并在运行时按名称执行它们。
使用这些批注预定义查询并管理它们的结果集。
@NamedQuery
@NamedQueries
@NamedNativeQuery
@NamedNativeQueries
@QueryHint
@ColumnResult
@EntityResult
@FieldResult
@SqlResultSetMapping
@SqlResultSetMappings
@AssociationOverride
默认情况下,JPA 持续性提供程序自动假设子类继承超类中定义的持久属性及其关联映射。
如果继承的列定义对实体不正确(例如,如果继承的列名与已经存在的数据模型不兼容或作为数据库中的列名无效),请使用 @AssociationOverride 批注自定义从 @MappedSuperclass 或 @Embeddable 继承的 @OneToOne 或 @ManyToOne 映射,以更改与字段或属性关联的 @JoinColumn。
如果有多个要进行的 @AssociationOverride 更改,则必须使用 @AssociationOverrides。
要自定义基本映射以更改它的 @Column,请使用 @AttributeOverride。
表 1-4 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-2 @AssociationOverride 属性
属性 必需 说明
joinColumns
必需
要指定映射到持久属性的连接列,请将 joinColums 设置为 JoinColumn 实例的数组(请参阅 @JoinColumn)。
映射类型将与可嵌套类或映射的超类中定义的类型相同。
name
必需
如果使用了基于属性的访问,则映射的为嵌入对象中的属性名称,如果使用了基于字段的访问,则映射的为字段名称。
示例 1-4 显示了示例 1-5 中的实体扩展的 @MappedSuperclass。示例 1-5 显示了如何在实体子类中使用 @AssociationOverride 覆盖 @MappedSuperclass Employee 中定义(默认情况下)的 @JoinColumn 以便关联到 Address。
如果使用 @AssociationOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDR_ID
*
WAGE
如果不使用 @AssociationOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDRESS
*
WAGE
示例 1-1 @MappedSuperclass
@MappedSuperclass public class Employee { @Id protected Integer id; @Version protected Integer version; @ManyToOne protected Address address; ... }
示例 1-2 @AssociationOverride
@Entity@AssociationOverride(name="address", joinColumns=@JoinColumn(name="ADDR_ID"))public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; ... }
@AssociationOverrides
如果需要指定多个 @AssociationOverride,则必需使用一个 @AssociationOverrides 批注指定所有关联覆盖。
表 1-5 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-3 @AssociationOverrides 属性
属性 必需 说明
value
必需
要指定两个或更多覆盖,请将 value 设置为 AssociationOverride 实例的数组(请参阅 @AssociationOverride)。
示例 1-6 显示了如何使用此批注指定两个关联覆盖。
示例 1-3 @AssociationOverrides
@Entity @AssociationOverrides({ @AssociationOverride(name="address", joinColumn=@Column(name="ADDR_ID")), @AssociationOverride(name="id", joinColumn=@Column(name="PTID")) }) public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; ... }
@AttributeOverride
默认情况下,JPA 持续性提供程序自动假设子类继承超类中定义的持久属性及其基本映射。
如果针对实体继承的列定义不正确,请使用 @AttributeOverride 批注自定义一个从 @MappedSuperclass 或 @Embeddable 继承的基本映射以更改与字段或属性关联的 @Column。(例如,如果继承的列名与事先存在的数据模型不兼容,或者作为数据库中的列名无效)。
如果有多个要进行的 @AttributeOverride 更改,则必须使用 @AttributeOverrides。
要自定义关联映射以更改它的 @JoinColumn,请使用 @AssociationOverride。
表 1-4 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-4 @AttributeOverride 属性
属性 必需 说明
column
必需
映射到持久属性的 @Column。映射类型将与可嵌套类或映射超类中定义的类型相同。
name
必需
如果使用了基于属性的访问,则映射的为嵌入对象中的属性名称,如果使用了基于字段的访问,则映射的为字段名称。
示例 1-4 显示了示例 1-5 中的实体扩展的 @MappedSuperclass。示例 1-5 显示了如何使用实体子类中的 @AttributeOverride 覆盖 @MappedSuperclass Employee 中定义(默认情况下)的 @Column,以便基本映射到 Address。
如果使用 @AttributeOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDR_STRING
*
WAGE
如果不使用 @AttributeOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDRESS
*
WAGE
示例 1-4 @MappedSuperclass
@MappedSuperclass public class Employee { @Id protected Integer id; @Version protected Integer version; protected String address; ... }
示例 1-5 @AttributeOverride
@Entity @AttributeOverride(name="address", column=@Column(name="ADDR_STRING")) public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; ... }
@AttributeOverrides
如果需要指定多个 @AttributeOverride,则必需使用一个 @AttributeOverrides 批注指定所有属性覆盖。
表 1-5 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-5 @AttributeOverrides 属性
属性 必需 说明
value
必需
要指定两个或更多属性覆盖,请将 value 设置为 AttributeOverride 实例的数组(请参阅 @AttributeOverride)。
示例 1-6 显示了如何使用此批注指定两个属性覆盖。
示例 1-6 @AttributeOverrides
@Entity @AttributeOverrides({ @AttributeOverride(name="address", column=@Column(name="ADDR_ID")), @AttributeOverride(name="id", column=@Column(name="PTID")) }) public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; public PartTimeEmployee() { ... } public Float getHourlyWage() { ... } public void setHourlyWage(Float wage) { ... } }
@Basic
默认情况下,JPA 持续性提供程序为大多数 Java 基元类型、基元类型的包装程序以及枚举自动配置一个 @Basic 映射。
使用 @Basic 批注:
*
将获取类型配置为 LAZY
*
如果空值不适合于应用程序,则将映射配置为禁止空值(针对非基元类型)
表 1-6 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-6 @Basic 属性
属性 必需 说明
fetch
可选
默认值:FetchType.EAGER。
默认情况下,JPA 持续性提供程序使用获取类型 EAGER:这将要求持续性提供程序运行时必须迫切获取数据。
如果这不适合于应用程序或特定的持久字段,请将 fetch 设置为 FetchType.LAZY:这将提示持续性提供程序在首次访问数据(如果可以)时应不急于获取数据。
optional
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设所有(非基元)字段和属性的值可以为空。
如果这并不适合于您的应用程序,请将 optional 设置为 false。
示例 1-7 显示了如何使用此批注为基本映射指定获取类型 LAZY。
示例 1-7 @Basic
@Entity public class Employee implements Serializable { ... @Basic(fetch=LAZY) protected String getName() { return name; } ... }
@Column
默认情况下,JPA 持续性提供程序假设每个实体的持久字段存储在其名称与持久字段的名称相匹配的数据库表列中。
使用 @Column 批注:
*
将持久字段与其他名称关联(如果默认列名难于处理、与事先存在的数据模型不兼容或作为数据库中的列名无效)
*
将持久字段与辅助表中的列关联(请参阅 @SecondaryTable)
*
微调数据库中列的特征
表 1-7 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-7 @Column 属性
属性 必需 说明
columnDefinition
可选
默认值:空 String。
默认情况下,JPA 使用最少量 SQL 创建一个数据库表列。
如果需要使用更多指定选项创建的列,请将 columnDefinition 设置为在针对列生成 DDL 时希望 JPA 使用的 SQL 片断。
注意:捕获批注中的 DDL 信息时,某些 JPA 持续性提供程序可以在生成数据库模式时使用此 DDL。例如,请参阅“用于 Java2DB 模式生成的 TopLink JPA 扩展”。
insertable
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设所有列始终包含在 SQL INSERT 语句中。
如果该列不应包含在这些语句中,请将 insertable 设置为 false。
length
可选
默认值: 255
默认情况下,JPA 持续性提供程序假设所有列在用于保存 String 值时的最大长度为 255 个字符。
如果该列不适合于您的应用程序或数据库,请将 length 设置为适合于您的数据库列的 int 值。
name
可选
默认值:JPA 持续性提供程序假设实体的每个持久字段都存储在其名称与持久字段或属性的名称相匹配的数据库表列中。
要指定其他列名,请将 name 设置为所需的 String 列名。
nullable
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设允许所有列包含空值。
如果不允许该列包含空值,请将 nullable 设置为 false。
precision
可选
默认值: 0.
默认情况下,JPA 持续性提供程序假设所有列在用于保存十进制(精确数字)值时的精度为 0。
如果该精度不适合于您的应用程序或数据库,请将 precision 设置为相应的 int 精度。
scale
可选
默认值: 0.
默认情况下,JPA 持续性提供程序假设所有列在用于保存十进制(精确数字)值时的伸缩度为 0。
如果该伸缩度不适合于您的应用程序或数据库,请将 scale 设置为相应的 int 精度。
table
可选
默认值:JPA 持续性提供程序假设实体的所有持久字段都存储到一个其名称为实体名称的数据库表中(请参阅 @Table)。
如果该列与辅助表关联(请参阅 @SecondaryTable),请将 name 设置为相应辅助表名称的 String 名称,如示例 1-8 所示。
unique
可选
默认值:false。
默认情况下,JPA 持续性提供程序假设允许所有列包含重复值。
如果不允许该列包含重复值,请将 unique 设置为 true。设置为 true 时,这相当于在表级别使用 @UniqueConstraint。
updatable
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设列始终包含在 SQL UPDATE 语句中。
如果该列不应包含在这些语句中,请将 updatable 设置为 false。
示例 1-8 显示了如何使用此批注使 JPA 将 empId 持久保存到辅助表 EMP_HR 中的列 EMP_NUM。默认情况下,JPA 将 empName 持久保存到主表 Employee 中的列 empName。
示例 1-8 @Column
@Entity @SecondaryTable(name="EMP_HR") public class Employee implements Serializable { ... @Column(name="EMP_NUM", table="EMP_HR") private Long empId; private String empName; ... }
@ColumnResult
执行 @NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。
使用 @ColumnResult 批注返回标量值。标量类型由您在 @ColumnResult 中标识的列类型确定。
有关详细信息,另请参阅 @EntityResult、@FieldResult 和 @SqlResultSetMapping。
表 1-8 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-8 @ColumnResult 属性
属性 必需 说明
name
必需
在原生 SQL 查询的 SELECT 语句中将 name 设置为列名的 String 等效形式。如果在 SELECT 中使用列别名(AS 语句),则将 name 设置为列别名。
示例 1-9 显示了如何使用此批注将 Item(请参阅示例 1-10)标量 name 包含在结果列表(请参阅示例 1-11)中。在该示例中,结果列表将为 Object 数组的 List,如:{[Order, "Shoes"], [Order, "Socks"], ...}。
示例 1-9 使用 @ColumnResult 的 Order 实体
@SqlResultSetMapping( name="OrderResults", entities={ @EntityResult( entityClass=Order.class, fields={ @FieldResult(name="id", column="order_id"), @FieldResult(name="quantity", column="order_quantity"), @FieldResult(name="item", column="order_item") } ) }, columns={ @ColumnResult( name="item_name" ) } ) @Entity public class Order { @Id protected int id; protected long quantity; protected Item item; ... }
示例 1-10 Item 实体
@Entity public class Item { @Id protected int id; protected String name; ... }
示例 1-11 结合使用 @SqlResultSetMapping 与 @ColumnResult 的原生查询
Query q = entityManager.createNativeQuery( "SELECT o.id AS order_id, " + "o.quantity AS order_quantity, " + "o.item AS order_item, " + "i.name AS item_name, " + "FROM Order o, Item i " + "WHERE (order_quantity > 25) AND (order_item = i.id)", "OrderResults" ); List resultList = q.getResultList(); // List of Object arrays:{[Order, "Shoes"], [Order, "Socks"], ...}
@DiscriminatorColumn
默认情况下,当 @Inheritance 属性策略为 InheritanceType.SINGLE_TABLE 或 JOINED 时,JPA 持续性提供程序将创建一个名为 DTYPE 的标识符列以区分继承层次中的类。
使用 @DiscriminatorColumn 批注:
*
指定一个标识符列名(如果数据模型中的列名不是默认列名 DTYPE)。
*
指定一个适用于应用程序或事先存在的数据模型的标识符列长度
*
微调数据库中的标识符列的特征
表 1-9 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-9 @DiscriminatorColumn 属性
属性 必需 说明
columnDefinition
可选
默认值:空 String。
默认情况下,JPA 持续性提供程序使用最少量 SQL 创建一个数据库表列。
如果需要使用更多指定选项创建的列,请将 columnDefinition 设置为在针对列生成 DDL 时希望 JPA 使用的 SQL 片断。
discriminatorType
可选
默认值:DiscriminatorType.STRING。
默认情况下,JPA 持续性提供程序假设标识符类型为 String。
如果要使用其他类型,请将 discriminatorType 设置为 DiscriminatorType.CHAR 或 DiscriminatorType.INTEGER。
您的 @DiscriminatorValue 必须符合此类型。
length
可选
默认值: 31
默认情况下,JPA 持续性提供程序假设标识符列在用于保存 String 值时的最大长度为 255 个字符。
如果该列不适合于您的应用程序或数据库,请将 length 设置为适合于您的数据库列的 int 值。
您的 @DiscriminatorValue 必须符合此长度。
name
可选
默认值:JPA 持续性提供程序假设标识符列名为“DTYPE”。
要指定其他列名,请将 name 设置为所需的 String 列名。
示例 1-12 显示了如何使用此批注指定一个名为 DISC、类型为 STRING、长度为 20 的标识符列。在本示例中,该类的 @DiscriminatorValue 指定为 CUST。示例 1-13 中的子类将它自己的 @DiscriminatorValue 指定为 VIP。在 Customer 和 ValuedCustomer 中,@DiscriminatorValue 的值必须可以转换为由 @DiscriminatorColumn 属性 discriminatorType 指定的类型,并且必须符合 @DiscriminatorColumn 属性 length。
示例 1-12 @DiscriminatorColumn 和 @DiscriminatorValue — 根类
@Entity @Table(name="CUST") @Inheritance(strategy=SINGLE_TABLE) @DiscriminatorColumn(name="DISC", discriminatorType=STRING, length=20) @DiscriminatorValue(value-"CUST") public class Customer { ... }
示例 1-13 @DiscriminatorValue — 子类
@Entity @DiscriminatorValue(value="VIP") public class ValuedCustomer extends Customer { ... }
@DiscriminatorValue
默认情况下,当 @Inheritance 属性策略为 InheritanceType.SINGLE_TABLE 或 JOINED 时,JPA 持续性提供程序使用 @DiscriminatorColumn 按实体名称区分继承层次中的类(请参阅 @Entity)。
使用 @DiscriminatorValue 批注指定用于区分此继承层次中的实体的标识符值:
*
如果实体名称不适合于此应用程序
*
匹配现有的数据库模式
表 1-10 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-10 @DiscriminatorValue 属性
属性 必需 说明
value
必需
将 value 设置为符合 @DiscriminatorColumn 属性 discriminatorType 和 length 的标识符值的 String 等效形式。
示例 1-14 显示了如何使用此批注指定一个名为 DISC、类型为 STRING、长度为 20 的标识符列。在本示例中,该类的 @DiscriminatorValue 指定为 CUST。示例 1-15 中的子类将它自己的 @DiscriminatorValue 指定为 VIP。在 Customer 和 ValuedCustomer 中,@DiscriminatorValue 的值必须可以转换为由 @DiscriminatorColumn 属性 discriminatorType 指定的类型,并且必须符合 @DiscriminatorColumn 属性 length。
示例 1-14 @DiscriminatorColumn 和 @DiscriminatorValue — 根类
@Entity @Table(name="CUST") @Inheritance(strategy=SINGLE_TABLE) @DiscriminatorColumn(name="DISC", discriminatorType=STRING, length=20) @DiscriminatorValue(value-"CUST") public class Customer { ... }
示例 1-15 @DiscriminatorValue — 子类
@Entity @DiscriminatorValue(value="VIP") public class ValuedCustomer extends Customer { ... }
@Embeddable
默认情况下,JPA 持续性提供程序假设每个实体均持久保存到它自己的数据库表。
使用 @Embeddable 批注指定一个类,该类的实例存储为拥有实体的固有部分并共享该实体的身份。嵌入对象的每个持久属性或字段都将映射到实体的数据库表。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-16 显示了如何使用此批注指定:类 EmploymentPeriod 在用作批注为 @Embedded 的持久字段的类型时可以嵌套到实体中(请参阅示例 1-17)
示例 1-16 @Embeddable
@Embeddable public class EmploymentPeriod { java.util.Date startDate; java.util.Date endDate; ... }
@Embedded
默认情况下,JPA 持续性提供程序假设每个实体均持久保存到它自己的数据库表。
使用 @Embedded 批注指定一个持久字段,该字段的 @Embeddable 类型可以存储为拥有实体的固有部分,并共享该实体的身份。嵌入对象的每个持久属性或字段均映射到拥有实体的数据库表。
可以结合使用 @Embedded 和 @Embeddable 以建立严格所有权关系的模型,以便在删除了拥有对象的情况下还将删除被拥有的对象。
嵌入的对象不应映射到多个表。
默认情况下,@Embeddable 类中指定的列定义(请参阅 @Column)适用于 @Embedded 类。如果要覆盖这些列定义,请使用 @AttributeOverride。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-17 显示了如何使用该批注指定:@Embeddable 类 EmploymentPeriod(请参阅示例 1-16)可以使用指定的属性覆盖(请参阅 @AttributeOverride)嵌入到实体类中。如果不需要属性覆盖,则可以完全忽略 @Embedded 批注:JPA 持续性提供程序将推断出 EmploymentPeriod 是从它的 @Embeddable 批注进行嵌套。
示例 1-17 @Embedded
@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 方法。
这些方法的值相等性的语义必须与键映射到的数据库类型的数据库相等性一致。
或者,您可以使复合主键类成为非嵌入类(请参阅 @IdClass)。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-18 显示了一个批注为 @Embeddable 的典型复合主键类。示例1-19 显示了如何使用可嵌入的复合主键类(使用 @EmbeddedId 批注)配置一个实体。
示例 1-18 可嵌入复合主键类
@Embeddable public class EmployeePK implements Serializable { private String name; private long id; public EmployeePK() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } 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); } }
示例 1-19 @EmbeddedId
@Entity public class Employee implements Serializable { EmployeePK primaryKey; public Employee() { } @EmbeddedId public EmployeePK getPrimaryKey() { return primaryKey; } public void setPrimaryKey(EmployeePK pk) { primaryKey = pk; } ... }
@Entity
使用 @Entity 批注将普通的旧式 Java 对象 (POJO) 类指定为实体,并使其可用于 JPA 服务。必须将 POJO 类指定为实体,然后才可以使用任何其他 JPA 批注。
表 1-11 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-11 @Entity 属性
属性 必需 说明
name
可选
默认值:JPA 持续性提供程序假设实体名称是实体类的名称。在示例 1-20 中,默认 name 为“Employee”。
如果实体类名难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的表名无效,请将 name 设置为其他 String 值。
示例 1-20 显示了该批注的用法。
示例 1-20 @Entity
@Entity public class Employee implements Serializable { ... }
@EntityListeners
可以使用生命周期批注(请参阅生命周期事件批注)指定实体中的方法,这些方法在指定的生命周期事件发生时执行您的逻辑。
使用 @EntityListeners 批注将一个或多个实体监听程序类与 @Entity 或 @MappedSuperclass 关联,条件是您需要在指定的生命周期事件发生时执行逻辑,以及:
*
不希望在实体 API 中公开生命周期监听程序方法。
*
要在不同的实体类型之间共享生命周期监听程序逻辑。
当实体或子类上发生生命周期事件时,JPA 持续性提供程序将按监听程序定义的顺序通知每个实体监听程序,并调用使用相应的生命周期事件类型进行批注的实体监听程序方法(如果有)。
实体监听程序类具有以下特征:
*
它是一个普通的旧式 Java 对象 (POJO) 类
*
它有一个或多个具有以下签名的回调方法:
public void <MethodName>(Object)
可以指定参数类型 Object,或实体监听程序将与其关联的实体类的类型。
*
它用一个或多个生命周期事件批注对每个回调方法进行批注。
一个生命周期事件只能与一个回调监听程序方法关联,但某个给定的回调监听程序方法可以与多个生命周期事件关联。
如果使用实体监听程序,则可以管理哪些实体监听程序使用 @ExcludeDefaultListeners 和 @ExcludeSuperclassListeners 调用。
表 1-12 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-12 @EntityListeners 属性
属性 必需 说明
value
必需
要为 @Entity 或 @MappedSuperclass 指定实体监听程序类的列表,请将 value 设置为实体监听程序类的 Class 数组。
示例 1-21 显示了如何使用此批注将实体监听程序类 EmployeePersistListener(请参阅示例 1-22)和 EmployeeRemoveListener(请参阅示例 1-23)与实体 Employee 关联。示例 1-23 显示了您可以将多个生命周期事件与给定的实体监听程序类方法关联,但任何给定的生命周期事件只能在实体监听程序类中出现一次。
示例 1-21 @EntityListeners
@Entity @EntityListeners(value={EmployeePersistListner.class, EmployeeRemoveListener.class}) public class Employee implements Serializable { ... }
示例 1-22 EmployeePersistListener
public class EmployeePersistListener { @PrePersist employeePrePersist(Object employee) { ... } ... }
示例 1-23 EmployeeRemoveListener
public class EmployeeRemoveListener { @PreRemove @PostRemove employeePreRemove(Object employee) { ... } ... }
@EntityResult
执行 @NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。
使用 @EntityResult 批注返回实体。
有关详细信息,另请参阅 @ColumnResult、@FieldResult 和 @SqlResultSetMapping。
表 1-8 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-13 @EntityResult 属性
属性 必需 说明
entityClass
必需
将 entityClass 设置为由 SELECT 语句返回的实体的 Class。
discriminatorColumn
可选
默认值:空 String。
默认情况下,JPA 持续性提供程序假设 SELECT 语句中不包含标识符列(请参阅 @Inheritance)。
如果在 SELECT 语句中使用标识符列,请将 discriminatorColumn 设置为所使用的 String 列名。
fields
可选
默认值:空 FieldResult 数组。
默认情况下,JPA 持续性提供程序假设 SELECT 语句包含与返回的实体的所有字段或属性相对应的所有列,且 SELECT 语句中的列名对应于字段或属性名(未使用 AS 语句)。
如果 SELECT 语句只包含某些与返回的实体的字段或属性相对应的列,或 SELECT 语句中的列名并不对应于字段或属性名(使用了 AS 语句),请将 fields 设置为 @FieldResult 的数组,SELECT 语句中的每一列一个 @FieldResult。
示例 1-24 显示了如何使用此批注将 Order 和 Item(请参阅示例 1-25)实体包含在结果列表(请参阅示例 1-26)中。在该示例中,结果列表将为 Object 数组的 List,如:{[Order, Item], [Order, Item], ...}。
示例 1-24 使用 @EntityResult 的 Order 实体
@SqlResultSetMapping( name="OrderResults", entities={ @EntityResult( entityClass=Order.class, fields={ @FieldResult(name="id", column="order_id"), @FieldResult(name="quantity", column="order_quantity"), @FieldResult(name="item", column="order_item") } ), @EntityResult( entityClass=Item.class, fields={ @FieldResult(name="id", column="item_id"), @FieldResult(name="name", column="item_name"), } ) } ) @Entity public class Order { @Id protected int id; protected long quantity; protected Item item; ... }
示例 1-25 Item 实体
@Entity public class Item { @Id protected int id; protected String name; ... }
示例 1-26 结合使用 @SqlResultSetMapping 与 @EntityResult 的原生查询
Query q = entityManager.createNativeQuery( "SELECT o.id AS order_id, " + "o.quantity AS order_quantity, " + "o.item AS order_item, " + "i.id AS item_id, " + "i.name AS item_name, " + "FROM Order o, Item i " + "WHERE (order_quantity > 25) AND (order_item = i.id)", "OrderResults" ); List resultList = q.getResultList(); // List of Object arrays:{[Order, Item], [Order, Item], ...}
@Enumerated
默认情况下,JPA 持续性提供程序持久保存枚举常量的序数值。
使用 @Enumerated 批注指定在 String 值适合应用程序要求或与现有数据库模式匹配的情况下,JPA 持续性提供程序是否应持久保存枚举常量的序数值或 String 值。
该批注可以与 @Basic 一起使用。
表 1-14 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-14 @Enumerated 属性
属性 必需 说明
value
可选
默认值:EnumType.ORDINAL。
默认情况下,JPA 持续性提供程序假设对于映射到枚举常量的属性或字段,应持久保存序数值。在示例 1-28 中,当持久保存 Employee 时,EmployeeStatus 的序数值将写入数据库。
如果需要持久保存的枚举常量的 String 值,请将 value 设置为 EnumType.STRING。
根据示例 1-27 中的枚举常量,示例 1-28 显示了如何使用此批注指定在持久保存 Employee 时应将 SalaryRate 的 String 值写入数据库。默认情况下,会将 EmployeeStatus 的序数值写入数据库。
示例 1-27 枚举常量
public enum EmployeeStatus {FULL_TIME, PART_TIME, CONTRACT} public enum SalaryRate {JUNIOR, SENIOR, MANAGER, EXECUTIVE}
示例 1-28 @Enumerated
@Entity public class Employee { ... public EmployeeStatus getStatus() { ... } @Enumerated(STRING) public SalaryRate getPayScale() { ... } ... }
@ExcludeDefaultListeners
默认监听程序是 orm.xml 文件中指定的一个生命周期事件监听程序类,该类应用于持续性单元(请参阅 @PersistenceUnit)中的所有实体。在调用任何其他实体监听程序(请参阅 @EntityListeners)之前,JPA 持续性提供程序首先按照 orm.xml 文件中定义的顺序调用默认监听程序(如果有)。
如果默认监听程序行为不适用,请使用 @ExcludeDefaultListeners 批注覆盖(并阻止)针对给定 @Entity 或 @MappedSuperclass 执行的默认监听程序。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-29 显示了如何使用此批注指定不应对 Employee 实体执行默认监听程序。
示例 1-29 @ExcludeDefaultListeners
@Entity @ExcludeDefaultListeners public class Employee implements Serializable { ... }
@ExcludeSuperclassListeners
如果继承层次中的 @Entity 和 @MappedSuperclass 类定义了 @EntityListeners,则默认情况下,JPA 持续性提供程序将在调用子类监听程序之前调用超类监听程序。
如果超类监听程序行为不适用,则使用 @ExcludeSuperclassListeners 批注覆盖(并阻止)针对给定 @Entity 或 @MappedSuperclass 执行的超类监听程序。
@ExcludeSuperclassListeners 批注不影响默认监听程序(请参阅 @ExcludeDefaultListeners)。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-29 显示了如何使用此批注指定不应对 PartTimeEmployee 实体执行超类监听程序 EmployeeListener,而是执行默认监听程序和子类监听程序 PartTimeEmployeeListener1 和 PartTimeEmployeeListener2。
示例 1-30 超类级别的实体监听程序
@MappedSuperclass @EntityListeners(value={EmployeeListener.class}) public class Employee { ... }
示例 1-31 子类级别的 @ExcludeSuperclassListeners
@Entity @ExcludeSuperclassListeners @EntityListners(value={PartTimeEmployeeListener1.class, PartTimeEmployeeListener2.class}) public class PartTimeEmployee extends Employee { ... }
@FieldResult
执行 @NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。
默认情况下,JPA 持续性提供程序假设在使用 @EntityResult 返回实体时,SELECT 语句将包含与返回的实体的所有字段或属性相对应的所有列,且 SELECT 语句中的列名对应于字段或属性名(未使用 AS 语句)。
如果 SELECT 语句只包含某些与返回的实体的字段或属性相对应的列,或 SELECT 语句中的列名并不对应于字段或属性名(使用了 AS 语句),则在使用 @EntityResult 返回实体时,请使用 @FieldResult 批注将 SELECT 语句中的列映射到字段或属性。
有关详细信息,另请参阅 @ColumnResult 和 @SqlResultSetMapping。
表 1-15 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-15 @FieldResult 属性
属性 必需 说明
column
必需
将 column 设置为 SELECT 语句中使用的列的 String 名称。如果在 SELECT 中使用列别名(AS 语句),请将 column 设置为列别名。
name
必需
将 name 设置为实体的字段或属性名(作为 String),该名称对应于 column 属性指定的列名。
示例 1-32 显示了如何使用此批注将 Order 和 Item(请参阅示例 1-33)实体包含在结果列表(请参阅示例 1-34)中。在该示例中,结果列表将为 Object 数组的 List,如:{[Order, Item], [Order, Item], ...}。
示例 1-32 使用 @EntityResult 和 @FieldResult 的 Order 实体
@SqlResultSetMapping( name="OrderResults", entities={ @EntityResult( entityClass=Order.class, fields={ @FieldResult(name="id", column="order_id"), @FieldResult(name="quantity", column="order_quantity"), @FieldResult(name="item", column="order_item") } ), @EntityResult( entityClass=Item.class, fields={ @FieldResult(name="id", column="item_id"), @FieldResult(name="name", column="item_name"), } ) } ) @Entity public class Order { @Id protected int id; protected long quantity; protected Item item; ... }
示例 1-33 Item 实体
@Entity public class Item { @Id protected int id; protected String name; ... }
示例 1-34 结合使用 @SqlResultSetMapping 与 @EntityResult 的原生查询
Query q = entityManager.createNativeQuery( "SELECT o.id AS order_id, " + "o.quantity AS order_quantity, " + "o.item AS order_item, " + "i.id AS item_id, " + "i.name AS item_name, " + "FROM Order o, Item i " + "WHERE (order_quantity > 25) AND (order_item = i.id)", "OrderResults" ); List resultList = q.getResultList(); // List of Object arrays:{[Order, Item], [Order, Item], ...}
@GeneratedValue
默认情况下,JPA 持续性提供程序管理为实体主键提供的唯一标识符(请参阅 @Id)。
如果要微调此机制以实现以下目的,请使用 @GeneratedValue 批注:
*
如果您感觉另一个生成器类型更适合于数据库或应用,则覆盖持续性提供程序为数据库选择的身份值生成的类型
*
如果此名称难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的主键生成器名称无效,则覆盖持续性提供程序选择的主键生成器名称
表 1-16 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-16 @GeneratedValue 属性
属性 必需 说明
generator
可选
默认值:JPA 持续性提供程序为它选择的主键生成器分配一个名称。
如果该名称难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的主键生成器名称无效,则将 generator 设置为要使用的 String 生成器名称。
strategy
可选
默认值:GenerationType.AUTO。
默认情况下,JPA 持续性提供程序选择最适合于基础数据库的主键生成器类型。
如果您感觉另一个生成器类型更适合于数据库或应用程序,请将 strategy 设置为所需的 GeneratorType:
*
IDENTITY — 指定持续性提供程序使用数据库身份列
*
AUTO — 指定持续性提供程序应选择一个最适合于基础数据库的主键生成器。
*
SEQUENCE — 指定持续性提供程序使用数据库序列(请参阅 @SequenceGenerator)
*
TABLE — 指定持续性提供程序为使用基础数据库表的实体分配主键以确保唯一性(请参阅 @TableGenerator)
示例 1-35 显示了如何使用此批注指示持续性提供程序使用名为 CUST_SEQ、类型为 GeneratorType.SEQUENCE 的主键生成器。
示例 1-35 @GeneratedValue
@Entity public class Employee implements Serializable { ... @Id @GeneratedValue(strategy=SEQUENC
在 JPA 之前,Java EE 应用程序将持续类表示为容器管理的实体 bean。使用 JPA,您可以将任何普通的旧式 Java 对象 (POJO) 类指定为 JPA 实体:一个应使用 JPA 持续性提供程序的服务将其非临时字段持久保存到关系数据库(在 Java EE EJB 容器的内部或在简单 Java SE 应用程序中的 EJB 容器的外部)的 Java 对象。
使用 JPA 时,可以使用批注配置实体的 JPA 行为。批注是一种使用元数据修饰 Java 源代码的简单表达方法,它编译为相应的 Java 类文件,以便在运行时由 JPA 持续性提供程序解释以管理 JPA 行为。
例如,要将 Java 类指定为 JPA 实体,请使用 [color=red]@Entity[/color] 批注,如下所示:
@Entity public class Employee implements Serializable { ... }
您可以有选择地使用批注来修饰实体类以覆盖默认值。这称作按异常进行配置 (configuration by exception)。
本参考广泛引用了 [color=red]JSR-220 Enterprise JavaBean 版本 3.0[/color] Java 持续性 API 规范,以按类别汇总批注信息(请参阅[color=red]表 1-1[/color]),并解释了何时以及如何使用这些批注来自定义 JPA 行为,以满足应用程序的需要。
有关详细信息,请参阅:
*
[color=red]批注索引[/color]
*
[color=red] 完整的 JPA 批注 Javadoc[/color]
表 1-1 按类别划分的 JPA 批注
类别 说明 批注
实体
默认情况下,JPA 持续性提供程序假设 Java 类是非持续类,并且仅当使用此批注对其进行修饰的情况下才可用于 JPA 服务。
使用此批注将普通的旧式 Java 对象 (POJO) 类指定为实体,以便可以将它用于 JPA 服务。
要将类用于 JPA 服务,必须将该类指定为 JPA 实体(使用此批注或 orm.xml 文件)。
[color=red]@Entity[/color]
数据库模式属性
默认情况下,JPA 持续性提供程序假设实体名称对应于同名的数据库表,且实体的数据成员名称对应于同名的数据库列。
使用这些批注覆盖此默认行为,并微调对象模型与数据模型之间的关系。
@Table
@SecondaryTable
@SecondaryTables
@Column
@JoinColumn
@JoinColumns
@PrimaryKeyJoinColumn
@PrimaryKeyJoinColumns
@JoinTable
@UniqueConstraint
身份
默认情况下,JPA 持续性提供程序假设每个实体必须至少有一个用作主键的字段或属性。
使用这些批注指定以下项之一:
*
一个 @Id
*
多个 @Id 和一个 @IdClass
*
一个 @EmbeddedId
还可以使用这些批注微调数据库维护实体身份的方式。
@Id
@IdClass
@EmbeddedId
@GeneratedValue
@SequenceGenerator
@TableGenerator
直接映射
默认情况下,JPA 持续性提供程序为大多数 Java 基元类型、基元类型的包装程序以及 enums 自动配置一个 Basic 映射。
使用这些批注微调数据库实现这些映射的方式。
@Basic
@Enumerated
@Temporal
@Lob
@Transient
关系映射
JPA 持续性提供程序要求您显式映射关系。
使用这些批注指定实体关系的类型和特征,以微调数据库实现这些关系的方式。
@OneToOne
@ManyToOne
@OneToMany
@ManyToMany
@MapKey
@OrderBy
组合
默认情况下,JPA 持续性提供程序假设每个实体均映射到它自己的表。
使用这些批注覆盖其他实体拥有的此种实体行为。
@Embeddable
@Embedded
@AttributeOverride
@AttributeOverrides
@AssociationOverride
@AssociationOverrides
继承
默认情况下,JPA 持续性提供程序假设所有持久字段均由一个实体类定义。
如果实体类继承了一个或多个超类中的某些或所有持续字段,则使用这些批注。
@Inheritance
@DiscriminatorColumn
@DiscriminatorValue
@MappedSuperclass
@AssociationOverride
@AssociationOverrides
@AttributeOverride
@AttributeOverrides
锁定
默认情况下,JPA 持续性提供程序假设应用程序负责数据一致性。
使用此批注启用 JPA 管理的乐观锁定(推荐使用)。
@Version
生命周期回调事件
默认情况下,JPA 持续性提供程序处理所有持续性操作。
如果您要在实体生命周期内随时调用自定义逻辑,请使用这些批注将实体方法与 JPA 生命周期事件关联。图 1-1 演示了这些生命周期事件之间的关系。
@PrePersist
@PostPersist
@PreRemove
@PostRemove
@PreUpdate
@PostUpdate
@PostLoad
@EntityListeners
@ExcludeDefaultListeners
@ExcludeSuperclassListeners
实体管理器
在使用 JPA 持续性提供程序的应用程序中,您可以使用 EntityManager 实例执行所有持续性操作(创建、读取、更新和删除)。
使用这些批注将实体与实体管理器关联并自定义实体管理器的环境。
@PersistenceUnit
@PersistenceUnits
@PersistenceContext
@PersistenceContexts
@PersistenceProperty
查询
在使用 JPA 持续性提供程序的应用程序中,可以使用实体管理器动态创建和执行查询,也可以预定义查询并在运行时按名称执行它们。
使用这些批注预定义查询并管理它们的结果集。
@NamedQuery
@NamedQueries
@NamedNativeQuery
@NamedNativeQueries
@QueryHint
@ColumnResult
@EntityResult
@FieldResult
@SqlResultSetMapping
@SqlResultSetMappings
@AssociationOverride
默认情况下,JPA 持续性提供程序自动假设子类继承超类中定义的持久属性及其关联映射。
如果继承的列定义对实体不正确(例如,如果继承的列名与已经存在的数据模型不兼容或作为数据库中的列名无效),请使用 @AssociationOverride 批注自定义从 @MappedSuperclass 或 @Embeddable 继承的 @OneToOne 或 @ManyToOne 映射,以更改与字段或属性关联的 @JoinColumn。
如果有多个要进行的 @AssociationOverride 更改,则必须使用 @AssociationOverrides。
要自定义基本映射以更改它的 @Column,请使用 @AttributeOverride。
表 1-4 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-2 @AssociationOverride 属性
属性 必需 说明
joinColumns
必需
要指定映射到持久属性的连接列,请将 joinColums 设置为 JoinColumn 实例的数组(请参阅 @JoinColumn)。
映射类型将与可嵌套类或映射的超类中定义的类型相同。
name
必需
如果使用了基于属性的访问,则映射的为嵌入对象中的属性名称,如果使用了基于字段的访问,则映射的为字段名称。
示例 1-4 显示了示例 1-5 中的实体扩展的 @MappedSuperclass。示例 1-5 显示了如何在实体子类中使用 @AssociationOverride 覆盖 @MappedSuperclass Employee 中定义(默认情况下)的 @JoinColumn 以便关联到 Address。
如果使用 @AssociationOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDR_ID
*
WAGE
如果不使用 @AssociationOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDRESS
*
WAGE
示例 1-1 @MappedSuperclass
@MappedSuperclass public class Employee { @Id protected Integer id; @Version protected Integer version; @ManyToOne protected Address address; ... }
示例 1-2 @AssociationOverride
@Entity@AssociationOverride(name="address", joinColumns=@JoinColumn(name="ADDR_ID"))public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; ... }
@AssociationOverrides
如果需要指定多个 @AssociationOverride,则必需使用一个 @AssociationOverrides 批注指定所有关联覆盖。
表 1-5 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-3 @AssociationOverrides 属性
属性 必需 说明
value
必需
要指定两个或更多覆盖,请将 value 设置为 AssociationOverride 实例的数组(请参阅 @AssociationOverride)。
示例 1-6 显示了如何使用此批注指定两个关联覆盖。
示例 1-3 @AssociationOverrides
@Entity @AssociationOverrides({ @AssociationOverride(name="address", joinColumn=@Column(name="ADDR_ID")), @AssociationOverride(name="id", joinColumn=@Column(name="PTID")) }) public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; ... }
@AttributeOverride
默认情况下,JPA 持续性提供程序自动假设子类继承超类中定义的持久属性及其基本映射。
如果针对实体继承的列定义不正确,请使用 @AttributeOverride 批注自定义一个从 @MappedSuperclass 或 @Embeddable 继承的基本映射以更改与字段或属性关联的 @Column。(例如,如果继承的列名与事先存在的数据模型不兼容,或者作为数据库中的列名无效)。
如果有多个要进行的 @AttributeOverride 更改,则必须使用 @AttributeOverrides。
要自定义关联映射以更改它的 @JoinColumn,请使用 @AssociationOverride。
表 1-4 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-4 @AttributeOverride 属性
属性 必需 说明
column
必需
映射到持久属性的 @Column。映射类型将与可嵌套类或映射超类中定义的类型相同。
name
必需
如果使用了基于属性的访问,则映射的为嵌入对象中的属性名称,如果使用了基于字段的访问,则映射的为字段名称。
示例 1-4 显示了示例 1-5 中的实体扩展的 @MappedSuperclass。示例 1-5 显示了如何使用实体子类中的 @AttributeOverride 覆盖 @MappedSuperclass Employee 中定义(默认情况下)的 @Column,以便基本映射到 Address。
如果使用 @AttributeOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDR_STRING
*
WAGE
如果不使用 @AttributeOverride,则 Employee 表包含以下列:
*
ID
*
VERSION
*
ADDRESS
*
WAGE
示例 1-4 @MappedSuperclass
@MappedSuperclass public class Employee { @Id protected Integer id; @Version protected Integer version; protected String address; ... }
示例 1-5 @AttributeOverride
@Entity @AttributeOverride(name="address", column=@Column(name="ADDR_STRING")) public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; ... }
@AttributeOverrides
如果需要指定多个 @AttributeOverride,则必需使用一个 @AttributeOverrides 批注指定所有属性覆盖。
表 1-5 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-5 @AttributeOverrides 属性
属性 必需 说明
value
必需
要指定两个或更多属性覆盖,请将 value 设置为 AttributeOverride 实例的数组(请参阅 @AttributeOverride)。
示例 1-6 显示了如何使用此批注指定两个属性覆盖。
示例 1-6 @AttributeOverrides
@Entity @AttributeOverrides({ @AttributeOverride(name="address", column=@Column(name="ADDR_ID")), @AttributeOverride(name="id", column=@Column(name="PTID")) }) public class PartTimeEmployee extends Employee { @Column(name="WAGE") protected Float hourlyWage; public PartTimeEmployee() { ... } public Float getHourlyWage() { ... } public void setHourlyWage(Float wage) { ... } }
@Basic
默认情况下,JPA 持续性提供程序为大多数 Java 基元类型、基元类型的包装程序以及枚举自动配置一个 @Basic 映射。
使用 @Basic 批注:
*
将获取类型配置为 LAZY
*
如果空值不适合于应用程序,则将映射配置为禁止空值(针对非基元类型)
表 1-6 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-6 @Basic 属性
属性 必需 说明
fetch
可选
默认值:FetchType.EAGER。
默认情况下,JPA 持续性提供程序使用获取类型 EAGER:这将要求持续性提供程序运行时必须迫切获取数据。
如果这不适合于应用程序或特定的持久字段,请将 fetch 设置为 FetchType.LAZY:这将提示持续性提供程序在首次访问数据(如果可以)时应不急于获取数据。
optional
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设所有(非基元)字段和属性的值可以为空。
如果这并不适合于您的应用程序,请将 optional 设置为 false。
示例 1-7 显示了如何使用此批注为基本映射指定获取类型 LAZY。
示例 1-7 @Basic
@Entity public class Employee implements Serializable { ... @Basic(fetch=LAZY) protected String getName() { return name; } ... }
@Column
默认情况下,JPA 持续性提供程序假设每个实体的持久字段存储在其名称与持久字段的名称相匹配的数据库表列中。
使用 @Column 批注:
*
将持久字段与其他名称关联(如果默认列名难于处理、与事先存在的数据模型不兼容或作为数据库中的列名无效)
*
将持久字段与辅助表中的列关联(请参阅 @SecondaryTable)
*
微调数据库中列的特征
表 1-7 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-7 @Column 属性
属性 必需 说明
columnDefinition
可选
默认值:空 String。
默认情况下,JPA 使用最少量 SQL 创建一个数据库表列。
如果需要使用更多指定选项创建的列,请将 columnDefinition 设置为在针对列生成 DDL 时希望 JPA 使用的 SQL 片断。
注意:捕获批注中的 DDL 信息时,某些 JPA 持续性提供程序可以在生成数据库模式时使用此 DDL。例如,请参阅“用于 Java2DB 模式生成的 TopLink JPA 扩展”。
insertable
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设所有列始终包含在 SQL INSERT 语句中。
如果该列不应包含在这些语句中,请将 insertable 设置为 false。
length
可选
默认值: 255
默认情况下,JPA 持续性提供程序假设所有列在用于保存 String 值时的最大长度为 255 个字符。
如果该列不适合于您的应用程序或数据库,请将 length 设置为适合于您的数据库列的 int 值。
name
可选
默认值:JPA 持续性提供程序假设实体的每个持久字段都存储在其名称与持久字段或属性的名称相匹配的数据库表列中。
要指定其他列名,请将 name 设置为所需的 String 列名。
nullable
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设允许所有列包含空值。
如果不允许该列包含空值,请将 nullable 设置为 false。
precision
可选
默认值: 0.
默认情况下,JPA 持续性提供程序假设所有列在用于保存十进制(精确数字)值时的精度为 0。
如果该精度不适合于您的应用程序或数据库,请将 precision 设置为相应的 int 精度。
scale
可选
默认值: 0.
默认情况下,JPA 持续性提供程序假设所有列在用于保存十进制(精确数字)值时的伸缩度为 0。
如果该伸缩度不适合于您的应用程序或数据库,请将 scale 设置为相应的 int 精度。
table
可选
默认值:JPA 持续性提供程序假设实体的所有持久字段都存储到一个其名称为实体名称的数据库表中(请参阅 @Table)。
如果该列与辅助表关联(请参阅 @SecondaryTable),请将 name 设置为相应辅助表名称的 String 名称,如示例 1-8 所示。
unique
可选
默认值:false。
默认情况下,JPA 持续性提供程序假设允许所有列包含重复值。
如果不允许该列包含重复值,请将 unique 设置为 true。设置为 true 时,这相当于在表级别使用 @UniqueConstraint。
updatable
可选
默认值:true。
默认情况下,JPA 持续性提供程序假设列始终包含在 SQL UPDATE 语句中。
如果该列不应包含在这些语句中,请将 updatable 设置为 false。
示例 1-8 显示了如何使用此批注使 JPA 将 empId 持久保存到辅助表 EMP_HR 中的列 EMP_NUM。默认情况下,JPA 将 empName 持久保存到主表 Employee 中的列 empName。
示例 1-8 @Column
@Entity @SecondaryTable(name="EMP_HR") public class Employee implements Serializable { ... @Column(name="EMP_NUM", table="EMP_HR") private Long empId; private String empName; ... }
@ColumnResult
执行 @NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。
使用 @ColumnResult 批注返回标量值。标量类型由您在 @ColumnResult 中标识的列类型确定。
有关详细信息,另请参阅 @EntityResult、@FieldResult 和 @SqlResultSetMapping。
表 1-8 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-8 @ColumnResult 属性
属性 必需 说明
name
必需
在原生 SQL 查询的 SELECT 语句中将 name 设置为列名的 String 等效形式。如果在 SELECT 中使用列别名(AS 语句),则将 name 设置为列别名。
示例 1-9 显示了如何使用此批注将 Item(请参阅示例 1-10)标量 name 包含在结果列表(请参阅示例 1-11)中。在该示例中,结果列表将为 Object 数组的 List,如:{[Order, "Shoes"], [Order, "Socks"], ...}。
示例 1-9 使用 @ColumnResult 的 Order 实体
@SqlResultSetMapping( name="OrderResults", entities={ @EntityResult( entityClass=Order.class, fields={ @FieldResult(name="id", column="order_id"), @FieldResult(name="quantity", column="order_quantity"), @FieldResult(name="item", column="order_item") } ) }, columns={ @ColumnResult( name="item_name" ) } ) @Entity public class Order { @Id protected int id; protected long quantity; protected Item item; ... }
示例 1-10 Item 实体
@Entity public class Item { @Id protected int id; protected String name; ... }
示例 1-11 结合使用 @SqlResultSetMapping 与 @ColumnResult 的原生查询
Query q = entityManager.createNativeQuery( "SELECT o.id AS order_id, " + "o.quantity AS order_quantity, " + "o.item AS order_item, " + "i.name AS item_name, " + "FROM Order o, Item i " + "WHERE (order_quantity > 25) AND (order_item = i.id)", "OrderResults" ); List resultList = q.getResultList(); // List of Object arrays:{[Order, "Shoes"], [Order, "Socks"], ...}
@DiscriminatorColumn
默认情况下,当 @Inheritance 属性策略为 InheritanceType.SINGLE_TABLE 或 JOINED 时,JPA 持续性提供程序将创建一个名为 DTYPE 的标识符列以区分继承层次中的类。
使用 @DiscriminatorColumn 批注:
*
指定一个标识符列名(如果数据模型中的列名不是默认列名 DTYPE)。
*
指定一个适用于应用程序或事先存在的数据模型的标识符列长度
*
微调数据库中的标识符列的特征
表 1-9 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-9 @DiscriminatorColumn 属性
属性 必需 说明
columnDefinition
可选
默认值:空 String。
默认情况下,JPA 持续性提供程序使用最少量 SQL 创建一个数据库表列。
如果需要使用更多指定选项创建的列,请将 columnDefinition 设置为在针对列生成 DDL 时希望 JPA 使用的 SQL 片断。
discriminatorType
可选
默认值:DiscriminatorType.STRING。
默认情况下,JPA 持续性提供程序假设标识符类型为 String。
如果要使用其他类型,请将 discriminatorType 设置为 DiscriminatorType.CHAR 或 DiscriminatorType.INTEGER。
您的 @DiscriminatorValue 必须符合此类型。
length
可选
默认值: 31
默认情况下,JPA 持续性提供程序假设标识符列在用于保存 String 值时的最大长度为 255 个字符。
如果该列不适合于您的应用程序或数据库,请将 length 设置为适合于您的数据库列的 int 值。
您的 @DiscriminatorValue 必须符合此长度。
name
可选
默认值:JPA 持续性提供程序假设标识符列名为“DTYPE”。
要指定其他列名,请将 name 设置为所需的 String 列名。
示例 1-12 显示了如何使用此批注指定一个名为 DISC、类型为 STRING、长度为 20 的标识符列。在本示例中,该类的 @DiscriminatorValue 指定为 CUST。示例 1-13 中的子类将它自己的 @DiscriminatorValue 指定为 VIP。在 Customer 和 ValuedCustomer 中,@DiscriminatorValue 的值必须可以转换为由 @DiscriminatorColumn 属性 discriminatorType 指定的类型,并且必须符合 @DiscriminatorColumn 属性 length。
示例 1-12 @DiscriminatorColumn 和 @DiscriminatorValue — 根类
@Entity @Table(name="CUST") @Inheritance(strategy=SINGLE_TABLE) @DiscriminatorColumn(name="DISC", discriminatorType=STRING, length=20) @DiscriminatorValue(value-"CUST") public class Customer { ... }
示例 1-13 @DiscriminatorValue — 子类
@Entity @DiscriminatorValue(value="VIP") public class ValuedCustomer extends Customer { ... }
@DiscriminatorValue
默认情况下,当 @Inheritance 属性策略为 InheritanceType.SINGLE_TABLE 或 JOINED 时,JPA 持续性提供程序使用 @DiscriminatorColumn 按实体名称区分继承层次中的类(请参阅 @Entity)。
使用 @DiscriminatorValue 批注指定用于区分此继承层次中的实体的标识符值:
*
如果实体名称不适合于此应用程序
*
匹配现有的数据库模式
表 1-10 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-10 @DiscriminatorValue 属性
属性 必需 说明
value
必需
将 value 设置为符合 @DiscriminatorColumn 属性 discriminatorType 和 length 的标识符值的 String 等效形式。
示例 1-14 显示了如何使用此批注指定一个名为 DISC、类型为 STRING、长度为 20 的标识符列。在本示例中,该类的 @DiscriminatorValue 指定为 CUST。示例 1-15 中的子类将它自己的 @DiscriminatorValue 指定为 VIP。在 Customer 和 ValuedCustomer 中,@DiscriminatorValue 的值必须可以转换为由 @DiscriminatorColumn 属性 discriminatorType 指定的类型,并且必须符合 @DiscriminatorColumn 属性 length。
示例 1-14 @DiscriminatorColumn 和 @DiscriminatorValue — 根类
@Entity @Table(name="CUST") @Inheritance(strategy=SINGLE_TABLE) @DiscriminatorColumn(name="DISC", discriminatorType=STRING, length=20) @DiscriminatorValue(value-"CUST") public class Customer { ... }
示例 1-15 @DiscriminatorValue — 子类
@Entity @DiscriminatorValue(value="VIP") public class ValuedCustomer extends Customer { ... }
@Embeddable
默认情况下,JPA 持续性提供程序假设每个实体均持久保存到它自己的数据库表。
使用 @Embeddable 批注指定一个类,该类的实例存储为拥有实体的固有部分并共享该实体的身份。嵌入对象的每个持久属性或字段都将映射到实体的数据库表。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-16 显示了如何使用此批注指定:类 EmploymentPeriod 在用作批注为 @Embedded 的持久字段的类型时可以嵌套到实体中(请参阅示例 1-17)
示例 1-16 @Embeddable
@Embeddable public class EmploymentPeriod { java.util.Date startDate; java.util.Date endDate; ... }
@Embedded
默认情况下,JPA 持续性提供程序假设每个实体均持久保存到它自己的数据库表。
使用 @Embedded 批注指定一个持久字段,该字段的 @Embeddable 类型可以存储为拥有实体的固有部分,并共享该实体的身份。嵌入对象的每个持久属性或字段均映射到拥有实体的数据库表。
可以结合使用 @Embedded 和 @Embeddable 以建立严格所有权关系的模型,以便在删除了拥有对象的情况下还将删除被拥有的对象。
嵌入的对象不应映射到多个表。
默认情况下,@Embeddable 类中指定的列定义(请参阅 @Column)适用于 @Embedded 类。如果要覆盖这些列定义,请使用 @AttributeOverride。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-17 显示了如何使用该批注指定:@Embeddable 类 EmploymentPeriod(请参阅示例 1-16)可以使用指定的属性覆盖(请参阅 @AttributeOverride)嵌入到实体类中。如果不需要属性覆盖,则可以完全忽略 @Embedded 批注:JPA 持续性提供程序将推断出 EmploymentPeriod 是从它的 @Embeddable 批注进行嵌套。
示例 1-17 @Embedded
@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 方法。
这些方法的值相等性的语义必须与键映射到的数据库类型的数据库相等性一致。
或者,您可以使复合主键类成为非嵌入类(请参阅 @IdClass)。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-18 显示了一个批注为 @Embeddable 的典型复合主键类。示例1-19 显示了如何使用可嵌入的复合主键类(使用 @EmbeddedId 批注)配置一个实体。
示例 1-18 可嵌入复合主键类
@Embeddable public class EmployeePK implements Serializable { private String name; private long id; public EmployeePK() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } 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); } }
示例 1-19 @EmbeddedId
@Entity public class Employee implements Serializable { EmployeePK primaryKey; public Employee() { } @EmbeddedId public EmployeePK getPrimaryKey() { return primaryKey; } public void setPrimaryKey(EmployeePK pk) { primaryKey = pk; } ... }
@Entity
使用 @Entity 批注将普通的旧式 Java 对象 (POJO) 类指定为实体,并使其可用于 JPA 服务。必须将 POJO 类指定为实体,然后才可以使用任何其他 JPA 批注。
表 1-11 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-11 @Entity 属性
属性 必需 说明
name
可选
默认值:JPA 持续性提供程序假设实体名称是实体类的名称。在示例 1-20 中,默认 name 为“Employee”。
如果实体类名难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的表名无效,请将 name 设置为其他 String 值。
示例 1-20 显示了该批注的用法。
示例 1-20 @Entity
@Entity public class Employee implements Serializable { ... }
@EntityListeners
可以使用生命周期批注(请参阅生命周期事件批注)指定实体中的方法,这些方法在指定的生命周期事件发生时执行您的逻辑。
使用 @EntityListeners 批注将一个或多个实体监听程序类与 @Entity 或 @MappedSuperclass 关联,条件是您需要在指定的生命周期事件发生时执行逻辑,以及:
*
不希望在实体 API 中公开生命周期监听程序方法。
*
要在不同的实体类型之间共享生命周期监听程序逻辑。
当实体或子类上发生生命周期事件时,JPA 持续性提供程序将按监听程序定义的顺序通知每个实体监听程序,并调用使用相应的生命周期事件类型进行批注的实体监听程序方法(如果有)。
实体监听程序类具有以下特征:
*
它是一个普通的旧式 Java 对象 (POJO) 类
*
它有一个或多个具有以下签名的回调方法:
public void <MethodName>(Object)
可以指定参数类型 Object,或实体监听程序将与其关联的实体类的类型。
*
它用一个或多个生命周期事件批注对每个回调方法进行批注。
一个生命周期事件只能与一个回调监听程序方法关联,但某个给定的回调监听程序方法可以与多个生命周期事件关联。
如果使用实体监听程序,则可以管理哪些实体监听程序使用 @ExcludeDefaultListeners 和 @ExcludeSuperclassListeners 调用。
表 1-12 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-12 @EntityListeners 属性
属性 必需 说明
value
必需
要为 @Entity 或 @MappedSuperclass 指定实体监听程序类的列表,请将 value 设置为实体监听程序类的 Class 数组。
示例 1-21 显示了如何使用此批注将实体监听程序类 EmployeePersistListener(请参阅示例 1-22)和 EmployeeRemoveListener(请参阅示例 1-23)与实体 Employee 关联。示例 1-23 显示了您可以将多个生命周期事件与给定的实体监听程序类方法关联,但任何给定的生命周期事件只能在实体监听程序类中出现一次。
示例 1-21 @EntityListeners
@Entity @EntityListeners(value={EmployeePersistListner.class, EmployeeRemoveListener.class}) public class Employee implements Serializable { ... }
示例 1-22 EmployeePersistListener
public class EmployeePersistListener { @PrePersist employeePrePersist(Object employee) { ... } ... }
示例 1-23 EmployeeRemoveListener
public class EmployeeRemoveListener { @PreRemove @PostRemove employeePreRemove(Object employee) { ... } ... }
@EntityResult
执行 @NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。
使用 @EntityResult 批注返回实体。
有关详细信息,另请参阅 @ColumnResult、@FieldResult 和 @SqlResultSetMapping。
表 1-8 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-13 @EntityResult 属性
属性 必需 说明
entityClass
必需
将 entityClass 设置为由 SELECT 语句返回的实体的 Class。
discriminatorColumn
可选
默认值:空 String。
默认情况下,JPA 持续性提供程序假设 SELECT 语句中不包含标识符列(请参阅 @Inheritance)。
如果在 SELECT 语句中使用标识符列,请将 discriminatorColumn 设置为所使用的 String 列名。
fields
可选
默认值:空 FieldResult 数组。
默认情况下,JPA 持续性提供程序假设 SELECT 语句包含与返回的实体的所有字段或属性相对应的所有列,且 SELECT 语句中的列名对应于字段或属性名(未使用 AS 语句)。
如果 SELECT 语句只包含某些与返回的实体的字段或属性相对应的列,或 SELECT 语句中的列名并不对应于字段或属性名(使用了 AS 语句),请将 fields 设置为 @FieldResult 的数组,SELECT 语句中的每一列一个 @FieldResult。
示例 1-24 显示了如何使用此批注将 Order 和 Item(请参阅示例 1-25)实体包含在结果列表(请参阅示例 1-26)中。在该示例中,结果列表将为 Object 数组的 List,如:{[Order, Item], [Order, Item], ...}。
示例 1-24 使用 @EntityResult 的 Order 实体
@SqlResultSetMapping( name="OrderResults", entities={ @EntityResult( entityClass=Order.class, fields={ @FieldResult(name="id", column="order_id"), @FieldResult(name="quantity", column="order_quantity"), @FieldResult(name="item", column="order_item") } ), @EntityResult( entityClass=Item.class, fields={ @FieldResult(name="id", column="item_id"), @FieldResult(name="name", column="item_name"), } ) } ) @Entity public class Order { @Id protected int id; protected long quantity; protected Item item; ... }
示例 1-25 Item 实体
@Entity public class Item { @Id protected int id; protected String name; ... }
示例 1-26 结合使用 @SqlResultSetMapping 与 @EntityResult 的原生查询
Query q = entityManager.createNativeQuery( "SELECT o.id AS order_id, " + "o.quantity AS order_quantity, " + "o.item AS order_item, " + "i.id AS item_id, " + "i.name AS item_name, " + "FROM Order o, Item i " + "WHERE (order_quantity > 25) AND (order_item = i.id)", "OrderResults" ); List resultList = q.getResultList(); // List of Object arrays:{[Order, Item], [Order, Item], ...}
@Enumerated
默认情况下,JPA 持续性提供程序持久保存枚举常量的序数值。
使用 @Enumerated 批注指定在 String 值适合应用程序要求或与现有数据库模式匹配的情况下,JPA 持续性提供程序是否应持久保存枚举常量的序数值或 String 值。
该批注可以与 @Basic 一起使用。
表 1-14 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-14 @Enumerated 属性
属性 必需 说明
value
可选
默认值:EnumType.ORDINAL。
默认情况下,JPA 持续性提供程序假设对于映射到枚举常量的属性或字段,应持久保存序数值。在示例 1-28 中,当持久保存 Employee 时,EmployeeStatus 的序数值将写入数据库。
如果需要持久保存的枚举常量的 String 值,请将 value 设置为 EnumType.STRING。
根据示例 1-27 中的枚举常量,示例 1-28 显示了如何使用此批注指定在持久保存 Employee 时应将 SalaryRate 的 String 值写入数据库。默认情况下,会将 EmployeeStatus 的序数值写入数据库。
示例 1-27 枚举常量
public enum EmployeeStatus {FULL_TIME, PART_TIME, CONTRACT} public enum SalaryRate {JUNIOR, SENIOR, MANAGER, EXECUTIVE}
示例 1-28 @Enumerated
@Entity public class Employee { ... public EmployeeStatus getStatus() { ... } @Enumerated(STRING) public SalaryRate getPayScale() { ... } ... }
@ExcludeDefaultListeners
默认监听程序是 orm.xml 文件中指定的一个生命周期事件监听程序类,该类应用于持续性单元(请参阅 @PersistenceUnit)中的所有实体。在调用任何其他实体监听程序(请参阅 @EntityListeners)之前,JPA 持续性提供程序首先按照 orm.xml 文件中定义的顺序调用默认监听程序(如果有)。
如果默认监听程序行为不适用,请使用 @ExcludeDefaultListeners 批注覆盖(并阻止)针对给定 @Entity 或 @MappedSuperclass 执行的默认监听程序。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-29 显示了如何使用此批注指定不应对 Employee 实体执行默认监听程序。
示例 1-29 @ExcludeDefaultListeners
@Entity @ExcludeDefaultListeners public class Employee implements Serializable { ... }
@ExcludeSuperclassListeners
如果继承层次中的 @Entity 和 @MappedSuperclass 类定义了 @EntityListeners,则默认情况下,JPA 持续性提供程序将在调用子类监听程序之前调用超类监听程序。
如果超类监听程序行为不适用,则使用 @ExcludeSuperclassListeners 批注覆盖(并阻止)针对给定 @Entity 或 @MappedSuperclass 执行的超类监听程序。
@ExcludeSuperclassListeners 批注不影响默认监听程序(请参阅 @ExcludeDefaultListeners)。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-29 显示了如何使用此批注指定不应对 PartTimeEmployee 实体执行超类监听程序 EmployeeListener,而是执行默认监听程序和子类监听程序 PartTimeEmployeeListener1 和 PartTimeEmployeeListener2。
示例 1-30 超类级别的实体监听程序
@MappedSuperclass @EntityListeners(value={EmployeeListener.class}) public class Employee { ... }
示例 1-31 子类级别的 @ExcludeSuperclassListeners
@Entity @ExcludeSuperclassListeners @EntityListners(value={PartTimeEmployeeListener1.class, PartTimeEmployeeListener2.class}) public class PartTimeEmployee extends Employee { ... }
@FieldResult
执行 @NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。
默认情况下,JPA 持续性提供程序假设在使用 @EntityResult 返回实体时,SELECT 语句将包含与返回的实体的所有字段或属性相对应的所有列,且 SELECT 语句中的列名对应于字段或属性名(未使用 AS 语句)。
如果 SELECT 语句只包含某些与返回的实体的字段或属性相对应的列,或 SELECT 语句中的列名并不对应于字段或属性名(使用了 AS 语句),则在使用 @EntityResult 返回实体时,请使用 @FieldResult 批注将 SELECT 语句中的列映射到字段或属性。
有关详细信息,另请参阅 @ColumnResult 和 @SqlResultSetMapping。
表 1-15 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-15 @FieldResult 属性
属性 必需 说明
column
必需
将 column 设置为 SELECT 语句中使用的列的 String 名称。如果在 SELECT 中使用列别名(AS 语句),请将 column 设置为列别名。
name
必需
将 name 设置为实体的字段或属性名(作为 String),该名称对应于 column 属性指定的列名。
示例 1-32 显示了如何使用此批注将 Order 和 Item(请参阅示例 1-33)实体包含在结果列表(请参阅示例 1-34)中。在该示例中,结果列表将为 Object 数组的 List,如:{[Order, Item], [Order, Item], ...}。
示例 1-32 使用 @EntityResult 和 @FieldResult 的 Order 实体
@SqlResultSetMapping( name="OrderResults", entities={ @EntityResult( entityClass=Order.class, fields={ @FieldResult(name="id", column="order_id"), @FieldResult(name="quantity", column="order_quantity"), @FieldResult(name="item", column="order_item") } ), @EntityResult( entityClass=Item.class, fields={ @FieldResult(name="id", column="item_id"), @FieldResult(name="name", column="item_name"), } ) } ) @Entity public class Order { @Id protected int id; protected long quantity; protected Item item; ... }
示例 1-33 Item 实体
@Entity public class Item { @Id protected int id; protected String name; ... }
示例 1-34 结合使用 @SqlResultSetMapping 与 @EntityResult 的原生查询
Query q = entityManager.createNativeQuery( "SELECT o.id AS order_id, " + "o.quantity AS order_quantity, " + "o.item AS order_item, " + "i.id AS item_id, " + "i.name AS item_name, " + "FROM Order o, Item i " + "WHERE (order_quantity > 25) AND (order_item = i.id)", "OrderResults" ); List resultList = q.getResultList(); // List of Object arrays:{[Order, Item], [Order, Item], ...}
@GeneratedValue
默认情况下,JPA 持续性提供程序管理为实体主键提供的唯一标识符(请参阅 @Id)。
如果要微调此机制以实现以下目的,请使用 @GeneratedValue 批注:
*
如果您感觉另一个生成器类型更适合于数据库或应用,则覆盖持续性提供程序为数据库选择的身份值生成的类型
*
如果此名称难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的主键生成器名称无效,则覆盖持续性提供程序选择的主键生成器名称
表 1-16 列出了此批注的属性。有关更多详细信息,请参阅 API。
表 1-16 @GeneratedValue 属性
属性 必需 说明
generator
可选
默认值:JPA 持续性提供程序为它选择的主键生成器分配一个名称。
如果该名称难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的主键生成器名称无效,则将 generator 设置为要使用的 String 生成器名称。
strategy
可选
默认值:GenerationType.AUTO。
默认情况下,JPA 持续性提供程序选择最适合于基础数据库的主键生成器类型。
如果您感觉另一个生成器类型更适合于数据库或应用程序,请将 strategy 设置为所需的 GeneratorType:
*
IDENTITY — 指定持续性提供程序使用数据库身份列
*
AUTO — 指定持续性提供程序应选择一个最适合于基础数据库的主键生成器。
*
SEQUENCE — 指定持续性提供程序使用数据库序列(请参阅 @SequenceGenerator)
*
TABLE — 指定持续性提供程序为使用基础数据库表的实体分配主键以确保唯一性(请参阅 @TableGenerator)
示例 1-35 显示了如何使用此批注指示持续性提供程序使用名为 CUST_SEQ、类型为 GeneratorType.SEQUENCE 的主键生成器。
示例 1-35 @GeneratedValue
@Entity public class Employee implements Serializable { ... @Id @GeneratedValue(strategy=SEQUENC