2008年(60)
分类: Java
2008-04-28 09:31:40
默认情况下,在实体关联中,JPA 持续性提供程序使用一个基于现有名称(如字段或属性名称)的数据库模式,以便它可以自动确定要使用的单个连接列(包含外键的列)。
在以下条件下使用 @JoinColumn
批注:
默认连接列名称难于处理、是一个保留字、与预先存在的数据模型不兼容或作为数据库中的列名无效
您需要使用外部表中的列(非主键列)进行连接
您想要使用两个或更多连接列(请参阅 )
您想要使用一个连接表(请参阅 )
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-19 @JoinColumn 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
默认值:空 JPA 使用最少量 SQL 创建一个数据库表列。 如果需要使用更多指定选项创建列,请将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设它可以插入到所有表列中。 如果该列为只读,请将 |
|
|
默认值:如果使用一个连接列,则 JPA 持续性提供程序假设外键列的名称是以下名称的连接:
如果实体中没有这样的引用关系属性或字段(请参阅 ),则连接列名称格式化为以下名称的连接:实体名称 +“_”+ 被引用的主键列的名称。 这是外键列的名称。如果连接针对“一对一”或“多对一”实体关系,则该列位于源实体的表中。如果连接针对“多对多”实体关系,则该列位于连接表(请参阅 )中。 如果连接列名难于处理、是一个保留字、与预先存在的数据模型不兼容或作为数据库中的列名无效,请将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设允许所有列包含空值。 如果不允许该列包含空值,请将 |
|
|
默认值:如果使用一个连接列,则 JPA 持续性提供程序假设在实体关系中,被引用的列名是被引用的主键列的名称。 如果在连接表(请参阅 )中使用,则被引用的键列位于拥有实体(如果连接是反向连接定义的一部分,则为反向实体)的实体表中。 要指定其他列名,请将 |
|
|
默认值:JPA 持续性提供程序假设实体的所有持久字段存储到一个名称为实体类名称的数据库表中(请参阅 )。 如果该列与辅助表关联(请参阅 ),请将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设允许所有列包含重复值。 如果不允许该列包含重复值,请将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设它可以更新所有表列。 如果该列为只读,则将 |
显示了如何使用此批注使 JPA 将数据库表 Employee
列 ADDR_ID
用作连接列。
示例 1-43 @JoinColumn
@Entity public class Employee implements Serializable { ... @ManyToOne @JoinColumn(name="ADDR_ID") public Address getAddress() { return address; } }
默认情况下,在实体关联中,JPA 持续性提供程序假设使用一个连接列。
如果要指定两个或更多连接列(即复合主键),请使用 @JoinColumns
批注。
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-20 @JoinColumns 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
要指定两个或更多连接列,请将 |
显示了如何使用此批注指定两个连接列的名称:Employee
表中的 ADDR_ID
(其中包含 Address
表列 ID
中的外键值)以及 Employee
表中的 ADDR_ZIP
(其中包含 Address
表列 ZIP
中的外键值)。
示例 1-44 @JoinColumns
@Entity public class Employee implements Serializable { ... @ManyToOne @JoinColumns({ @JoinColumn(name="ADDR_ID", referencedColumnName="ID"), @JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP") }) public Address getAddress() { return address; } ... }
默认情况下,JPA 持续性提供程序在映射多对多关联(或在单向的一对多关联中)的拥有方上的实体关联时使用一个连接表。连接表名称及其列名均在默认情况下指定,且 JPA 持续性提供程序假设:在关系的拥有方上的实体主表中,每个主键列有一个连接列。
如果您需要执行以下操作,请使用 @JoinTable
批注:
由于默认名称难于处理、是一个保留字、与预先存在的数据模型不兼容或作为数据库中的表名无效而更改连接表的名称
由于默认名称难于处理、是一个保留字、与预先存在的数据模型不兼容或作为数据库中的列名无效而更改连接表的列名称
使用特定目录或模式配置连接表
使用唯一约束配置一个或多个连接表列
每个实体使用多个连接列
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-21 @JoinTable 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
默认值:空 默认情况下,JPA 使用任何适用于数据库的默认目录。 如果默认目录不适合于应用程序,请将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设关联的被拥有方(或另一方)上有一个连接列:被拥有实体的主键列。JPA 通过连接被拥有实体的名称 +“_”+ 被引用的主键列的名称来命名该列。 如果这样的列名难于处理、是一个保留字、与预先存在的数据模型不兼容,或者如果要指定多个连接列,则将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设:拥有实体的每个主键列都有一个连接列。该持续性提供程序通过连接拥有实体的名称+“_”+ 被引用主键列的名称来命名这些列。 如果这样的列名难于处理、是一个保留字、与预先存在的数据模型不兼容,或者如果要指定多个连接列,则将 |
|
|
默认值:JPA 持续性提供程序通过使用下划线连接关联主表(拥有方优先)的表名来命名连接表。 如果这样的连接表难于处理、是一个保留字或与预先存在的数据模型不兼容,则将 |
|
|
默认值:空 默认情况下,JPA 使用任何适用于数据库的默认模式。 如果默认模式不适合于应用程序,则将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设连接表中的任何列均没有唯一约束。 如果唯一约束应用于该表中的一列或多列,则将 |
显示了如何使用此批注为 Employee
与 Project
之间实体的多对多关系指定一个名为 EMP_PROJ_EMP
的连接表。连接表中有两列:EMP_ID
和 PROJ_ID
。EMP_ID
列包含其主键列(被引用列)名为 ID
的 Employee
表中的主键值。PROJ_ID
列包含其主键列(被引用列)也名为 ID
的 Project
表中的主键值。
示例 1-45 @JoinTable
@Entity public class Employee implements Serializable { ... @ManyToMany @JoinTable( name="EJB_PROJ_EMP", joinColumns=@JoinColumn(name="EMP_ID", referencedColumnName="ID"), inverseJoinColumns=@JoinColumn(name="PROJ_ID", referencedColumnName="ID") ) public Collection getProjects() { return projects; } ... }
默认情况下,JPA 持续性提供程序假设所有持久数据均可以表示为典型的数据库数据类型。
结合使用 @Lob
批注与 映射,以指定持久属性或字段应作为大型对象持久保存到数据库支持的大型对象类型。
Lob 可以是二进制类型或字符类型。持续性提供程序从持久字段或属性的类型推断出 Lob 类型。
对于基于字符串和字符的类型,默认值为 Clob。在所有其他情况下,默认值为 Blob。
还可以使用 属性 columnDefinition
进一步改进 Lob
类型。
此批注没有属性。有关更多详细信息,请参阅 。
显示了如何使用此批注指定持久字段 pic
应作为 Blob
进行持久保存。
示例 1-46 @Lob
@Entity public class Employee implements Serializable { ... @Lob @Basic(fetch=LAZY) @Column(name="EMP_PIC", columnDefinition="BLOB NOT NULL") protected byte[] pic; ... }
默认情况下,JPA 为具有多对多多重性的为多值关联自动定义一个 @ManyToMany
映射。
使用 @ManyToMany
批注:
将获取类型配置为 LAZY
如果空值不适合于应用程序,则将映射配置为禁止空值(针对非基元类型)
由于所使用的 Collection
不是使用一般参数定义的,因此配置关联的目标实体
配置必须层叠到关联目标的操作:例如,如果删除了拥有实体,则确保还删除关联的目标
配置由持续性提供程序使用的连接表的详细信息(请参阅 )
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-22 @ManyToMany 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
默认值: 默认情况下,JPA 不会将任何持续性操作层叠到关联的目标。 如果希望某些或所有持续性操作层叠到关联的目标,请将
|
|
|
默认值: 默认情况下,JPA 持续性提供程序使用获取类型 如果这不适合于应用程序或特定的持久字段,请将 |
|
|
默认值:如果关系是单向的,则 JPA 持续性提供程序确定拥有该关系的字段。 如果关系是双向的,则将关联的反向(非拥有)一方上的 |
|
|
默认值:使用一般参数定义的 默认情况下,如果使用通过一般参数定义的 如果 |
和 显示了如何使用此批注在使用一般参数的 Customer
和 PhoneNumber
之间配置一个多对多映射。
示例 1-47 @ManyToMany — 使用一般参数的 Customer 类
@Entity public class Customer implements Serializable { ... @ManyToMany @JoinTable( name="CUST_PHONE", joinColumns= @JoinColumn(name="CUST_ID", referencedColumnName="ID"), inverseJoinColumns= @JoinColumn(name="PHONE_ID", referencedColumnName="ID") ) public SetgetPhones() { return phones; } ... }
示例 1-48 @ManyToMany — 使用一般参数的 PhoneNumber 类
@Entity public class PhoneNumber implements Serializable { ... @ManyToMany(mappedBy="phones") public SetgetCustomers() { return customers; } ... }
默认情况下,JPA 为指向具有多对一多重性的其他实体类的单值关联自动定义一个 ManyToOne
映射。
使用 @ManyToOne
批注:
将获取类型配置为 LAZY
如果空值不适合于应用程序,则将映射配置为禁止空值(针对非基元类型)
配置关联的目标实体(如果无法从被引用的对象类型推断出它)
配置必须层叠到关联目标的操作:例如,如果删除了拥有实体,则确保还删除关联的目标
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-23 @ManyToOne 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
默认值: 默认情况下,JPA 不会将任何持续性操作层叠到关联的目标。 如果希望某些或所有持续性操作层叠到关联的目标,请将
|
|
|
默认值: 默认情况下,JPA 持续性提供程序使用获取类型 如果这不适合于应用程序或特定的持久字段,请将 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设所有(非基元)字段和属性的值可以为空。 如果这并不适合于您的应用程序,请将 |
|
|
默认值:JPA 持续性提供程序从被引用的对象类型推断出关联的目标实体 如果持续性提供程序无法推断出目标实体的类型,则将关联拥有方上的 |
显示了如何使用此批注在使用一般参数的 Customer
(被拥有方)和 Order
(拥有方)之间配置一个多对一映射。
示例 1-49 @ManyToOne
@Entity public class Order implements Serializable { ... @ManyToOne(optional=false) @JoinColumn(name="CUST_ID", nullable=false, updatable=false) public Customer getCustomer() { return customer; } ... }
默认情况下,JPA 持续性提供程序假设关联实体的主键为 java.util.Map
类型的关联的 Map
键:
如果主键是批注为 的非复合主键,则该字段或属性的类型实例将用作 Map
键。
如果主键是批注为 的复合主键,则主键类的实例将用作 Map
键。
使用 @MapKey
批注:
将某个其他字段或属性指定为 Map
键(如果关联实体的主键不适合于应用程序)
指定一个嵌入的复合主键类(请参阅 )
指定的字段或属性必须具有唯一约束(请参阅 )。
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-24 @MapKey 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
默认值:默认情况下,JPA 持续性提供程序将关联实体的主键作为 如果要将某个其他字段或属性用作 |
在 中,Project 对作为 Map
的 Employee
实例拥有一对多关系。 显示了如何使用 @MapKey
批注指定此 Map
的键为 Employee
字段 empPK
,它是一个类型为 EmployeePK
(请参阅)的嵌入式复合主键(请参阅)。
示例 1-50 使用 @MapKey 的 Project 实体
@Entitypublic class Project { ...@OneToMany(mappedBy="project") @MapKey(name="empPK") public MapgetEmployees() { ... } ...}
示例 1-51 Employee 实体
@Entitypublic class Employee { @EmbeddedId public EmployeePK getEmpPK() { ... } ... @ManyToOne @JoinColumn(name="proj_id") public Project getProject() { ... }...}
示例 1-52 EmployeePK 复合主键类
@Embeddablepublic class EmployeePK { String name; Date birthDate;}
默认情况下,JPA 持续性提供程序假设实体的所有持久字段均在该实体中定义。
使用 @MappedSuperclass
批注指定一个实体类从中继承持久字段的超类。当多个实体类共享通用的持久字段或属性时,这将是一个方便的模式。
您可以像对实体那样使用任何直接和关系映射批注(如 和 )对该超类的字段和属性进行批注,但由于没有针对该超类本身的表存在,因此这些映射只适用于它的子类。继承的持久字段或属性属于子类的表。
可以在子类中使用 或 批注来覆盖超类的映射配置。
该批注没有属性。有关更多详细信息,请参阅 。
显示了如何使用此批注将 Employee
指定为映射超类。 显示了如何扩展实体中的此超类,以及如何在实体类中使用 以覆盖超类中设置的配置。
示例 1-53 @MappedSuperclass
@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) { ... } }
示例 1-54 扩展 @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) { ... } }
如果需要指定多个 ,则必须使用一个 @NamedNativeQueries
批注指定所有命名查询。
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-25 @NamedNativeQueries 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
要指定两个或更多属性覆盖,请将 |
显示了如何使用此批注指定两个命名原生查询。
示例 1-55 @NamedNativeQueries
@Entity @NamedNativeQueries({ @NamedNativeQuery( name="findAllPartTimeEmployees", query="SELECT * FROM EMPLOYEE WHERE PRT_TIME=1" ), @NamedNativeQuery( name="findAllSeasonalEmployees", query="SELECT * FROM EMPLOYEE WHERE SEASON=1" ) }) public class PartTimeEmployee extends Employee { ... }
在使用 JPA 持续性提供程序的应用程序中,可以使用实体管理器动态创建和执行查询,也可以预定义查询并在运行时按名称执行。
使用 @NamedNativeQuery
批注创建与 或 关联的预定义查询,这些查询:
使用基础数据库的原生 SQL
经常被使用
比较复杂并且难于创建
可以在不同实体之间共享
返回实体、标量值或两者的组合(另请参阅 、、 和 )
如果有多个要定义的 @NamedNativeQuery
,则必须使用 。
要预定义适合于任何数据库的可移植查询,请参阅 。
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-26 @NamedNativeQuery 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
要指定查询,请将 有关原生 SQL 查询语言的详细信息,请参阅数据库文档。 |
|
|
默认值:空 默认情况下,JPA 持续性提供程序假设 SQL 查询应完全按照 要微调查询的执行,可以选择将 |
|
|
要指定查询名称,请将 这是您在运行时调用查询所使用的名称(请参阅)。 |
|
|
默认值:JPA 持续性提供程序假设结果类是关联实体的 要指定结果类,请将 |
|
|
默认值:JPA 持续性提供程序假设原生 SQL 查询中的 要控制 JPA 持续性提供程序如何将 JDBC 结果集映射到实体字段或属性以及标量,请通过将 |
显示了如何使用 @NamedNativeQuery
批注定义一个使用基础数据库的原生 SQL 的查询。 显示了如何使用 EntityManager
获取此查询以及如何通过 Query
方法 getResultList
执行该查询。
示例 1-56 使用 @NamedNativeQuery 实现一个 Oracle 层次查询
@Entity @NamedNativeQuery( name="findAllEmployees", query="SELECT * FROM EMPLOYEE" ) public class Employee implements Serializable { ... }
示例 1-57 执行一个命名原生查询
Query queryEmployees = em.createNamedQuery("findAllEmployees"); Collection employees = queryEmployees.getResultList();
如果需要指定多个 ,则必须使用一个 @NamedQueries
批注指定所有命名查询。
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-27 @NamedQueries 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
要指定两个或更多属性覆盖,请将 |
显示了如何使用此批注指定两个命名查询。
示例 1-58 @NamedQueries
@Entity @NamedQueries({ @NamedQuery( name="findAllEmployeesByFirstName", query="SELECT OBJECT(emp) FROM Employee emp WHERE emp.firstName = :firstname" ), @NamedQuery( name="findAllEmployeesByLasttName", query="SELECT OBJECT(emp) FROM Employee emp WHERE emp.lasstName = :lastname" ) }) public class PartTimeEmployee extends Employee { ... }
在使用 JPA 持续性提供程序的应用程序中,可以使用实体管理器动态创建和执行查询,也可以预定义查询并在运行时按名称执行。
使用 @NamedQuery
批注创建与 或 关联的预定义查询,这些查询:
使用 JPA 查询语言(请参阅 规范,第 4 章)进行基于任何基础数据库的可移植执行
经常被使用
比较复杂并且难于创建
可以在不同实体之间共享
只返回实体(从不返回标量值),并只返回一个类型的实体
如果有多个要定义的 @NamedQuery
,则必须使用 。
要在已知的基础数据库中预定义原生 SQL 查询,请参阅 。使用原生 SQL 查询,您可以返回实体(包括不同类型的实体)、标量值或同时返回两者。
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-28 @NamedQuery 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
要指定查询,请将 有关 JPA 查询语言的详细信息,请参阅 规范的第 4 章。 |
|
|
默认值:空 默认情况下,JPA 持续性提供程序假设 SQL 查询应完全按照 如果您知道基础数据库在运行时的状态,则要微调查询的执行,可以选择将 |
|
|
要指定查询名称,请将 这是您在运行时调用查询所使用的名称(请参阅)。 |
显示了如何使用 @NamedQuery
批注定义一个JPA 查询语言查询,该查询使用名为 firstname
的参数。 显示了如何使用 EntityManager
获取此查询并使用 Query
方法 setParameter
设置 firstname
参数。
示例 1-59 使用 @NamedQuery 实现一个带参数的查询
@Entity @NamedQuery( name="findAllEmployeesByFirstName", query="SELECT OBJECT(emp) FROM Employee emp WHERE emp.firstName = :firstname" ) public class Employee implements Serializable { ... }
示例 1-60 执行命名查询
Query queryEmployeesByFirstName = em.createNamedQuery("findAllEmployeesByFirstName"); queryEmployeeByFirstName.setParameter("firstName", "John"); Collection employees = queryEmployessByFirstName.getResultList();
默认情况下,JPA 为具有一对多多重性的多值关联定义一个 OneToMany
映射。
使用 @OneToMany
批注:
将获取类型配置为 LAZY
由于所使用的 Collection
不是使用一般参数定义的,因此配置关联的目标实体
配置必须层叠到关联目标的操作:例如,如果删除了拥有实体,则确保还删除关联的目标
配置持续性提供程序对单向一对多关系使用的连接表(请参阅 )的详细信息
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-29 @OneToMany 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
默认值: 默认情况下,JPA 不会将任何持续性操作层叠到关联的目标。 如果希望某些或所有持续性操作层叠到关联的目标,请将
|
|
|
默认值: 默认情况下,JPA 持续性提供程序使用获取类型 如果这不适合于应用程序或特定的持久字段,请将 |
|
|
默认值:如果关系是单向的,则该持续性提供程序确定拥有该关系的字段。 如果关系是双向的,则将关联相反(非拥有)方上的 |
|
|
默认值:使用一般参数定义的 默认情况下,如果使用通过一般参数定义的 Collection,则持续性提供程序从被引用的对象类型推断出关联的目标实体。 如果 |
和 显示了如何使用此批注在使用一般参数的 Customer
(被拥有方)和 Order
(拥有方)之间配置一个一对多映射。
示例 1-61 @OneToMany - 使用一般参数的 Customer 类
@Entity public class Customer implements Serializable { ... @OneToMany(cascade=ALL, mappedBy="customer") public SetgetOrders() { return orders; } ... }
示例 1-62 @ManyToOne - 使用一般参数的 Order 类
@Entity public class Customer implements Serializable { ... @ManyToOne @JoinColumn(name="CUST_ID", nullable=false) public Customer getCustomer() { return customer; } ... }
默认情况下,JPA 为指向另一个具有一对一多重性的实体的单值关联定义一个 OneToOne
映射,并从被引用的对象类型推断出关联的目标实体。
使用 @OneToOne
批注:
将获取类型配置为 LAZY
如果空值不适合于应用程序,则将映射配置为禁止空值(针对非基元类型)
配置关联的目标实体(如果无法从被引用的对象类型推断出它)
配置必须层叠到关联目标的操作:例如,如果删除了拥有实体,则确保还删除关联的目标
列出了此批注的属性。有关更多详细信息,请参阅 。
表 1-30 @OneToOne 属性
属性 | 必需 | 说明 |
---|---|---|
|
|
默认值:空 默认情况下,JPA 不会将任何持续性操作层叠到关联的目标。 如果希望某些或所有持续性操作层叠到关联的目标,请将
|
|
|
默认值: 默认情况下,JPA 持续性提供程序使用获取类型 如果这不适合于应用程序或特定的持久字段,请将 |
|
|
默认值:JPA 持续性提供程序从被引用的对象类型推断出关联的目标实体 如果持续性提供程序无法推断关联的目标实体,则将关联的相反(非拥有)方上的 |
|
|
默认值: 默认情况下,JPA 持续性提供程序假设所有(非基元)字段和属性的值可以为空。 如果这并不适合于您的应用程序,请将 |
|
|
默认值:JPA 持续性提供程序从被引用的对象类型推断出关联的目标实体 如果持续性提供程序无法推断出目标实体的类型,则将关联的拥有方上的 |
和 显示了如何使用此批注在 Customer
(拥有方)和 CustomerRecord
(被拥有方)之间配置一个一对一映射。
示例 1-63 @OneToOne - Customer 类
@Entity public class Customer implements Serializable { ... @OneToOne(optional=false) @JoinColumn(name="CUSTREC_ID", unique=true, nullable=false, updatable=false) public CustomerRecord getCustomerRecord() { return customerRecord; } ... }
示例 1-64 @OneToOne - CustomerRecord 类
@Entity public class CustomerRecord implements Serializable { ... @OneToOne(optional=false, mappedBy="customerRecord") public Customer getCustomer() { return customer; } ... }