默认情况下,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; ...}执行 @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" ) })@Entitypublic class Order {@Idprotected int id;protected long quantity;protected Item item; ...}示例 1-10 Item 实体
@Entitypublic class Item {@Idprotected 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"], ...}默认情况下,当 @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 { ... }默认情况下,当 @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 { ... }默认情况下,JPA 持续性提供程序假设每个实体均持久保存到它自己的数据库表。
使用 @Embeddable 批注指定一个类,该类的实例存储为拥有实体的固有部分并共享该实体的身份。嵌入对象的每个持久属性或字段都将映射到实体的数据库表。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-16 显示了如何使用此批注指定:类 EmploymentPeriod 在用作批注为 @Embedded 的持久字段的类型时可以嵌套到实体中(请参阅示例 1-17)
示例 1-16 @Embeddable
@Embeddablepublic class EmploymentPeriod {java.util.Date startDate;java.util.Date endDate; ...}默认情况下,JPA 持续性提供程序假设每个实体均持久保存到它自己的数据库表。
使用 @Embedded 批注指定一个持久字段,该字段的 @Embeddable 类型可以存储为拥有实体的固有部分,并共享该实体的身份。嵌入对象的每个持久属性或字段均映射到拥有实体的数据库表。
可以结合使用 @Embedded 和 @Embeddable 以建立严格所有权关系的模型,以便在删除了拥有对象的情况下还将删除被拥有的对象。
嵌入的对象不应映射到多个表。
默认情况下,@Embeddable 类中指定的列定义(请参阅 @Column)适用于 @Embedded 类。如果要覆盖这些列定义,请使用 @AttributeOverride。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-17 显示了如何使用该批注指定:@Embeddable 类 EmploymentPeriod(请参阅示例 1-16)可以使用指定的属性覆盖(请参阅 @AttributeOverride)嵌入到实体类中。如果不需要属性覆盖,则可以完全忽略 @Embedded 批注:JPA 持续性提供程序将推断出 EmploymentPeriod 是从它的 @Embeddable 批注进行嵌套。
示例 1-17 @Embedded
@Entitypublic class Employee implements Serializable { ...@Embedded@AttributeOverrides({@AttributeOverride(name="startDate", column=@Column("EMP_START")),@AttributeOverride(name="endDate", column=@Column("EMP_END")) )public EmploymentPeriod getEmploymentPeriod() { ... } ...}使用 @EmbeddedId 批注指定一个由实体拥有的可嵌入复合主键类(通常由两个或更多基元类型或 JDK 对象类型组成)。从原有数据库映射时(此时数据库键由多列组成),通常将出现复合主键。
复合主键类具有下列特征:
它是一个普通的旧式 Java 对象 (POJO) 类。
它必须为 public,并且必须有一个 public 无参数构造函数。
如果使用基于属性的访问,则主键类的属性必须为 public 或 protected。
它必须是可序列化的。
它必须定义 equals 和 hashCode 方法。
这些方法的值相等性的语义必须与键映射到的数据库类型的数据库相等性一致。
或者,您可以使复合主键类成为非嵌入类(请参阅 @IdClass)。
此批注没有属性。有关更多详细信息,请参阅 API。
示例 1-18 显示了一个批注为 @Embeddable 的典型复合主键类。示例1-19 显示了如何使用可嵌入的复合主键类(使用 @EmbeddedId 批注)配置一个实体。
示例 1-18 可嵌入复合主键类
@Embeddablepublic 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
@Entitypublic class Employee implements Serializable{EmployeePK primaryKey;public Employee() { }@EmbeddedIdpublic EmployeePK getPrimaryKey() {return primaryKey; }public void setPrimaryKey(EmployeePK pk) {primaryKey = pk; } ...}使用 @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
@Entitypublic class Employee implements Serializable { ...}可以使用生命周期批注(请参阅生命周期事件批注)指定实体中的方法,这些方法在指定的生命周期事件发生时执行您的逻辑。
使用 @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 {@PrePersistemployeePrePersist(Object employee) { ... } ...}示例 1-23 EmployeeRemoveListener
public class EmployeeRemoveListener {@PreRemove@PostRemoveemployeePreRemove(Object employee) { ... } ...}执行 @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"), } ) })@Entitypublic class Order {@Idprotected int id;protected long quantity;protected Item item; ...}示例 1-25 Item 实体
@Entitypublic class Item {@Idprotected 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], ...}默认情况下,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_TIM 相关资源:敏捷开发V1.0.pptx