读书人

jpa 注脚

发布时间: 2012-07-23 09:42:19 作者: rapoo

jpa 注解

转:http://blog.csdn.net/gdweijin/article/details/5770674

?

核心提示:JPA 注解的几个要点 1.设置Pojo为实体 @Entity //标识这个pojo是一个jpa实体 public class Users implements Serializable{ } 2.设置表名 @Entity @Table (name= users ) //指定表名为users public class Users implements Serializable{ } 3.设置主键 public JPA 注解的几个要点1.设置Pojo为实体@Entity //标识这个pojo是一个jpa实体     public class Users implements Serializable {     }    2.设置表名@Entity     @Table(name = "users") //指定表名为users     public class Users implements Serializable {     }    3.设置主键public class Users implements Serializable {     @Id     private String userCode;    4. 设置字段类型通过@Column注解设置,包含的设置如下.name:字段名.unique:是否唯一.nullable:是否可以为空.inserttable:是否可以插入.updateable:是否可以更新.columnDefinition: 定义建表时创建此列的DDL.secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字。@Column(name = "user_code", nullable = false, length=32)//设置属性userCode对应的字段为user_code,长度为32,非空     private String userCode;     @Column(name = "user_wages", nullable = true, precision=12, scale=2)//设置属性wages对应的字段为user_wages,12位数字可保留两位小数,可以为空     private double wages;     @Temporal(TemporalType.DATE)//设置为时间类型     private Date joinDate;    5.字段排序在加载数据的时候可以为其指定顺序,使用@OrderBy注解实现@Table(name = "USERS")     public class User {     @OrderBy(name = "group_name ASC, name DESC")     private List books = new ArrayList();     }    6.主键生成策略public class Users implements Serializable {     @Id     @GeneratedValue(strategy=GenerationType.IDENTITY)//主键自增,注意,这种方式依赖于具体的数据库,如果数据库不支持自增主键,那么这个类型是没法用的     @Column(name = "user_id", nullable = false)     private int userId;           public class Users implements Serializable {     @Id     @GeneratedValue(strategy=GenerationType.TABLE)//通过一个表来实现主键id的自增,这种方式不依赖于具体的数据库,可以解决数据迁移的问题     @Column(name = "user_code", nullable = false)     private String userCode;           public class Users implements Serializable {     @Id     @GeneratedValue(strategy=GenerationType.SEQUENCE)//通过Sequence来实现表主键自增,这种方式依赖于数据库是否有SEQUENCE,如果没有就不能用     @SequenceGenerator(name="seq_user")     @Column(name = "user_id", nullable = false)     private int userId;    7.一对多映射关系有T_One和T_Many两个表,他们是一对多的关系,注解范例如下主Pojo@Entity     @Table(name = "T_ONE")     public class One implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @Column(name = "ONE_ID", nullable = false)     private String oneId;     @Column(name = "DESCRIPTION")     private String description;     @OneToMany(cascade = CascadeType.ALL, mappedBy = "oneId")//指向多的那方的pojo的关联外键字段     private Collection<Many> manyCollection;     子Pojo@Entity     @Table(name = "T_MANY")     public class Many implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @Column(name = "MANY_ID", nullable = false)     private String manyId;     @Column(name = "DESCRIPTION")     private String description;        @JoinColumn(name = "ONE_ID", referencedColumnName = "ONE_ID")//设置对应数据表的列名和引用的数据表的列名     @ManyToOne//设置在“一方”pojo的外键字段上     private One oneId;     8.多对多映射关系貌似多对多关系不需要设置级联,以前用hibernate的时候着实为多对多的级联头疼了一阵子,JPA的多对多还需要实际的尝试一下才能有所体会。估计JPA的多对多也是可以转换成两个一对多的。第一个Pojo@Entity     @Table(name = "T_MANYA")     public class ManyA implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @Column(name = "MANYA_ID", nullable = false)     private String manyaId;     @Column(name = "DESCRIPTION")     private String description;     @ManyToMany     @JoinTable(name = "TMANY1_TMANY2", joinColumns = {@JoinColumn(name = "MANYA_ID", referencedColumnName = "MANYA_ID")}, inverseJoinColumns = {@JoinColumn(name = "MANYB_ID", referencedColumnName = "MANYB_ID")})     private Collection<ManyB> manybIdCollection;     第二个Pojo@Entity     @Table(name = "T_MANYB")     public class ManyB implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @Column(name = "MANYB_ID", nullable = false)     private String manybId;     @Column(name = "DESCRIPTION")     private String description;     @ManyToMany(mappedBy = "manybIdCollection")     private Collection<ManyA> manyaIdCollection;     9.一对一映射关系主Pojo@Entity     @Table(name = "T_ONEA")     public class OneA implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @Column(name = "ONEA_ID", nullable = false)     private String oneaId;     @Column(name = "DESCRIPTION")     private String description;     @OneToOne(cascade = CascadeType.ALL, mappedBy = "oneA")//主Pojo这方的设置比较简单,只要设置好级联和映射到从Pojo的外键就可以了。     private OneB oneB;    从Pojo@Entity     @Table(name = "T_ONEB")     public class OneB implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @Column(name = "ONEA_ID", nullable = false)     private String oneaId;     @Column(name = "DESCRIPTION")     private String description;     @JoinColumn(name = "ONEA_ID", referencedColumnName = "ONEA_ID", insertable = false, updatable = false)//设置从方指向主方的关联外键,这个ONEA_ID其实是表T_ONEA的主键     @OneToOne     private OneA oneA;     10 大字段@Lob //对应Blob字段类型     @Column(name = "PHOTO")     private Serializable photo;     @Lob //对应Clob字段类型     @Column(name = "DESCRIPTION")     private String description;    11.瞬时字段不需要与数据库映射的字段,在保存的时候不需要保存倒数据库@Transient     private int tempValue;        public int getTempValue(){     get tempValue;     }        public void setTempValue(int value){     this.tempValue = value;     }    

?

JPA注解关键字: jpa注解 @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执行 使用 @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"], ...}<!----> @DiscriminatorColumn默认情况下,当 使用 @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默认情况下,当 使用 @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 批注指定一个类,该类的实例存储为拥有实体的固有部分并共享该实体的身份。嵌入对象的每个持久属性或字段都将映射到实体的数据库表。此批注没有属性。有关更多详细信息,请参阅 示例 1-16 显示了如何使用此批注指定:类 EmploymentPeriod 在用作批注为 @Embedded 的持久字段的类型时可以嵌套到实体中(请参阅示例 1-17 )示例 1-16 @Embeddable@Embeddablepublic class EmploymentPeriod {java.util.Date startDate;java.util.Date endDate;    ...}<!----> @Embedded默认情况下,JPA 持续性提供程序假设每个实体均持久保存到它自己的数据库表。使用 @Embedded 批注指定一个持久字段,该字段的 可以结合使用 @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使用 @EmbeddedId 批注指定一个由实体拥有的可嵌入复合主键类(通常由两个或更多基元类型或 JDK 对象类型组成)。从原有数据库映射时(此时数据库键由多列组成),通常将出现复合主键。复合主键类具有下列特征:它是一个普通的旧式 Java 对象 (POJO) 类。它必须为 public,并且必须有一个 public 无参数构造函数。如果使用基于属性的访问,则主键类的属性必须为 public 或 protected。它必须是可序列化的。它必须定义 equals 和 hashCode 方法。这些方法的值相等性的语义必须与键映射到的数据库类型的数据库相等性一致。或者,您可以使复合主键类成为非嵌入类(请参阅 此批注没有属性 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使用 @Entity 批注将普通的旧式 Java 对象 (POJO) 类指定为实体,并使其可用于 JPA 服务。必须将 POJO 类指定为实体,然后才可以使用任何其他 JPA 批注。 表 1-11 @Entity 属性属性 必需 说明 name   默认值 :JPA 持续性提供程序假设实体名称是实体类的名称。在示例 1-20 中,默认 name 为“Employee ”。如果实体类名难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的表名无效,请将 name 设置为其他 String 值。 示例 1-20 显示了该批注的用法。<!---->  示例 1-20 @Entity@Entitypublic 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 EmployeePersistListenerpublic class EmployeePersistListener {@PrePersistemployeePrePersist(Object employee) {    ...    }    ...}示例 1-23 EmployeeRemoveListenerpublic class EmployeeRemoveListener {@PreRemove@PostRemoveemployeePreRemove(Object employee) {    ...    }    ...}<!----> @EntityResult执行 使用 @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], ...}<!----> @Enumerated默认情况下,JPA 持续性提供程序持久保存枚举常量的序数值。使用 @Enumerated 批注指定在 String 值适合应用程序要求或与现有数据库模式匹配的情况下,JPA 持续性提供程序是否应持久保存枚举常量的序数值或 String 值。该批注可以与 @Basic 一起使用。<!----> <!----> <!----><!---->@NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。<!----> <!----> <!----><!---->生命周期事件批注 )指定实体中的方法,这些方法在指定的生命周期事件发生时执行您的逻辑。<!----><!---->表 1-11 列出了此批注的属性 API 。。有关更多详细信息,请参阅 <!----> <!----><!---->@IdClass )。<!----><!---->@Embeddable 类型可以存储为拥有实体的固有部分,并共享该实体的身份。嵌入对象的每个持久属性或字段均映射到拥有实体的数据库表。<!----><!----> API 。<!----> <!----><!---->@Inheritance 属性策略为 InheritanceType.SINGLE_TABLE 或 JOINED 时,JPA 持续性提供程序使用 @DiscriminatorColumn 按实体名称区分继承层次中的类(请参阅 @Entity )。<!----> <!----><!---->@Inheritance 属性策略为 InheritanceType.SINGLE_TABLE 或 JOINED 时,JPA 持续性提供程序将创建一个名为 DTYPE 的标识符列以区分继承层次中的类。<!----> <!----> <!----><!---->@NamedNativeQuery 时,它可以返回实体(包括不同类型的实体)、标量值或实体和标量值的组合。<!----><!---->

?

JPA作为Java EE的规范,它只是提供了一种标准的API。程序员若要使用JPA,仍需要选择JPA的实现框架。通过本章的学习,读者将能够了解与不同的JPA实现框架相关的知识,以便在实际的项目中做出合适的选择。

Hibernate是最流行的ORM框架之一,也是最早实现JPA的规范框架之一。它被JBoss收购后,目前作为JBoss的一个开源框架,它遵循LGPL v2.1开源许可协议,官方主页是http://www.hibernate.org/。

Hibernate 3.2以及以后的版本开始支持JPA,如图14-1所示为Hibernate框架包含的所有子项目。其中,涉及JPA的子项目有三个,它们分别是:

Hibernate Core:Hibernate框架的核心实现。

Hibernate Annotations:支持JDK 5.0的注释。

Hibernate EntityManager:支持JPA的实现。

Hibernate JPA自定义配置可以通过多种方式进行配置,如下面列举的几种方法。

方法一:在persistence.xml文件中配置,如下所示。

?jpa 注脚jpa 注脚
    <persistence><persistence-unit name="jpaUnit" transaction-type="RESOURCE_LOCAL"><provider>org.hibernate.ejb.HibernatePersistence</provider><properties><property name="hibernate.connection.driver_class"value="com.mysql.jdbc.Driver" /><property name="hibernate.connection.url"value="jdbc:mysql://localhost:3306/jpademo" /><property name="hibernate.connection.username" value="root" /><property name=" hibernate.show_sql " value="true"/></properties> </persistence-unit></persistence>

    ?

    其中,“hibernate.show_sql ”为可配置的属性,Hibernate JPA还提供很多不同属性的配置。

    方法二:通过代码,在创建EntityManagerFactory时指定,如下所示。

    Map configOverrides = new HashMap();
    configOverrides.put("hibernate.format_sql ", true);
    EntityManagerFactory programmaticEmf =
    Persistence.createEntityManagerFactory("jpaUnit", configOverrides

    当同时使用方法一和方法二设置时,方法二的方式为有效的配置。

    方法三:使用Hibernate 专有的配置文件来配置,但首先要在persistence.xml文件中配置“hibernate.ejb.cfgfile”指定配置文件的位置,如下所示。

    ?jpa 注脚jpa 注脚
      <persistence><persistence-unit name="jpaUnit" transaction-type="RESOURCE_LOCAL"><provider>org.hibernate.ejb.HibernatePersistence</provider><properties><property name="hibernate.connection.driver_class"value="com.mysql.jdbc.Driver" /><property name="hibernate.connection.url"value="jdbc:mysql://localhost:3306/jpademo" /><property name="hibernate.connection.username" value="root" /><!—可选,配置Hibernate配置文件--> < property name="hibernate.ejb.cfgfile" value="/com/fengmanfei/jpa/hibernate.cfg.xml"/ ></properties> </persistence-unit></persistence>

      ?

      其中,“/com/fengmanfei/jpa/hibernate.cfg.xml”为Hibernate配置文件的保存位置。使用这种方式,适用于将现有Hibernate应用移植到JPA应用中来。但要注意,方法三的优先级最低,如果与方法一和方法二冲突,则方法一或方法二中的配置有效。

      方法一和方法二是JPA的标准配置,方法三是Hibernate特有的配置。并不是所有的属性都可以通过这三种方式配置,其中一些属性必须通过方法一和方法二来配置,这些属性的详细说明如下所示。

      属性名:hibernate.ejb.classcache.<classname>

      描述:指定缓存实体对象,<classname>为缓存类的全名,值为缓存类型,以逗号分隔。

      示例如下:

      <property name="hibernate.ejb.classcache. com.fengmanfei.jpa.entity.Customer" value="read-write"/>

      属性名:hibernate.ejb.collectioncache.<collectionrole>

      描述:指定集合实体类缓存,设置同上。<collectionrole>为集合类的全名,值为缓存类型,以逗号分隔。

      示例如下:

      <property name="hibernate.ejb.collectioncache.com.fengmanfei.jpa.entity.Customer. orders"
      value="read-write , RegionName "/>

      ★ 提示 ★

      读者若想了解更多的缓存设置,请参阅JBoss Cache的相关文档。

      属性名:hibernate.ejb.cfgfile

      描述:指定使用Hibernate配置文件中的配置。

      示例如下:

      ?<property name="hibernate.ejb.cfgfile"? value="/com/fengmanfei/jpa/hibernate.cfg.xml"/ >

      属性名:hibernate.archieve.autodetection

      描述:创建Entity Manager时搜索文件的类型,多个值之间用逗号分隔。

      可选值:

      class:.class类文件。

      hbm:Hibernate 配置文件。

      默认两个都搜索。

      示例如下:

      <property name="hibernate.archive.autodetection" value="class,hbm"/>

      属性名:hibernate.ejb.interceptor

      描述:自定义拦截器类名,拦截器必须实现了org.hibernate.Interceptor接口,并且有无参的构造方法。

      示例如下:

      ?

      属性名:hibernate.ejb.naming_strategy

      描述:设置注释命名策略。

      可选值:

      EJB3NamingStrategy(默认):EJB3规范的命名实现。

      DefaultComponentSafeNamingStrategy:在默认的EJB3NamingStrategy上进行了扩展,允许在同一实体中使用两个同类型的嵌入对象而无须额外的声明。

      示例如下:

      ?

      属性名:hibernate.ejb.event.<eventtype>

      描述:配置事件监听器,其中<eventtype>为监听的事件类型,事件类型如表14-1中列举所示。而值则为具体监听器类的全名,如果有多个则使用逗号分隔。自定义拦截器类,拦截器必须实现了org.hibernate.Interceptor接口,并且有无参的构造方法,在JPA的环境中,尽量继承表14-1中的时间监听器类。

      表14-1? 可选的监听事件类型

      事件类型

      监听器类

      flush

      org.hibernate.ejb.event.EJB3FlushEventListener

      auto-flush

      org.hibernate.ejb.event.EJB3AutoFlushEventListener

      delete

      org.hibernate.ejb.event.EJB3DeleteEventListener

      flush-entity

      org.hibernate.ejb.event.EJB3FlushEntityEventListener

      merge

      org.hibernate.ejb.event.EJB3MergeEventListener

      create

      org.hibernate.ejb.event.EJB3PersistEventListener

      create-onflush

      org.hibernate.ejb.event.EJB3PersistOnFlushEventListener

      save

      org.hibernate.ejb.event.EJB3SaveEventListener

      save-update

      org.hibernate.ejb.event.EJB3SaveOrUpdateEventListener

      ?

      事件类型

      监听器类

      pre-insert

      org.hibernate.secure.JACCPreInsertEventListener,org.hibernate.valitator.event.ValidateEventListener

      pre-update

      org.hibernate.secure.JACCPreUpdateEventListener,org.hibernate.valitator.event.ValidateEventListener

      pre-delete

      org.hibernate.secure.JACCPreDeleteEventListener

      pre-load

      org.hibernate.secure.JACCPreLoadEventListener

      post-delete

      org.hibernate.ejb.event.EJB3PostDeleteEventListener

      post-insert

      org.hibernate.ejb.event.EJB3PostInsertEventListener

      post-load

      org.hibernate.ejb.event.EJB3PostLoadEventListener

      post-update

      org.hibernate.ejb.event.EJB3PostUpdateEventListener

      示例如下:

      <property name="hibernate.ejb.event.create" value="com.fengmanfei.listener.CreateListener" />

      其中,CreateListener继承org.hibernate.ejb.event.EJB3PersistEventListener类,代码如下所示。

      属性名:hibernate.ejb.discard_pc_on_close

      描述:是否在执行clear()时脱离持久化上下文。

      可选值:

      true:执行clear()时脱离持久化上下文。

      false(默认):执行clear()时不脱离持久化上下文。

      示例如下:

      Hibernate使用Apache commons-logging来为各种事件记录日志。commons-logging将直接将日志输出到Apache Log4j(如果在类路径中包括log4j.jar)或 JDK1.4 logging (如果运行在JDK1.4或以上的环境下)。

      如果使用Log4j,需要将log4j.properties文件保存在类路径中。Hibernate根据对日志进行了详细的分类,以便能够控制日志的的输出信息,这些日志类别如表14-2所示。

      表14-2? Hibernate JPA实现日志类别

      属性名

      描??? 述

      org.hibernate.SQL

      记录SQL DML语句

      org.hibernate.type

      记录JDBC参数

      org.hibernate.tool.hbm2ddl

      记录SQL DDL语句

      org.hibernate.pretty

      记录提交实体时,相关联的20个实体的状态

      org.hibernate.cache

      记录所有二级缓存

      org.hibernate.transaction

      记录事务相关的操作

      org.hibernate.jdbc

      记录获取JDBC资源的操作

      org.hibernate.hql.ast.AST

      记录HQL 和SQL AST的查询语句

      org.hibernate.secure

      记录JAAS认证请求

      org.hibernate

      记录所有信息,建议在调试开发阶段设置

      例如,下面为log4j.properties配置日志的示例代码。

      ★ 提示 ★

      有关各种缓存实现的详细区别,读者可以参阅Hiberante Core的相关文档。

      属性名:hibernate.cache.use_minimal_puts

      描述:是否优化二级缓存来最小化读写操作,集群时的缓存优化。

      可选值:

      true(默认):启用最小化读写操作。

      false:禁用最小化读写操作。

      示例如下:

      属性名:hibernate.cache.use_query_cache

      描述:是否缓存查询结果。

      可选值:

      true:缓存查询结果。

      false:不缓存查询结果。

      示例如下:

      属性名:hibernate.cache.use_second_level_cache

      描述:是否启用二级缓存。

      可选值:

      true:启用二级缓存。

      false:不使用二级缓存。

      示例如下:

      属性名:hibernate.cache.query_cache_factory

      描述:设置自定义的查询缓存类全名,缓存类必须实现org.hibernate.cache.QueryCache接口。

      可选值:

      org.hibernate.cache.StandardQueryCache(默认)。

      自定义缓存实现类。

      示例如下:

      属性名:hibernate.cache.region_prefix

      描述:二级缓存的前缀名称。

      示例如下:

      属性名:hibernate.cache.use_structured_entries

      描述:是否使用结构化的方式缓存对象。

      可选值:

      true:结构化方式缓存对象。

      false:不使用结构化的方式缓存对象。

      示例如下:

      Hibernate自定义JDBC和数据库配置属性如下所示。

      属性名:hibernate.jdbc.fetch_size

      描述:JDBC抓取记录的大小,相当于设置Statement.setFetchSize(),默认值为25。

      示例如下:

      <property name="hibernate.jdbc.batch_size" ?value=" 25”/>

      属性名:hibernate.jdbc.batch_versioned_data

      描述:JDBC执行批量操作时,是否同时更新版本数据。

      可选值:

      true(默认):执行批量操作executeBatch()返回成功的记录数,并且更新版本数据。

      false:批量操作后不更新版本数据。

      示例如下:

      属性名:hibernate.connection.username

      描述:数据连接的用户名。

      示例如下:

      属性名

      描??? 述

      DB2

      org.hibernate.dialect.DB2Dialect

      DB2 AS/400

      org.hibernate.dialect.DB2400Dialect

      DB2 OS390

      org.hibernate.dialect.DB2390Dialect

      PostgreSQL

      org.hibernate.dialect.PostgreSQLDialect

      MySQL

      org.hibernate.dialect.MySQLDialect

      MySQL InnoDB

      org.hibernate.dialect.MySQLInnoDBDialect

      MySQL with MyISAM

      org.hibernate.dialect.MySQLMyISAMDialect

      Oracle

      org.hibernate.dialect.OracleDialect

      Oracle 9i/10g

      org.hibernate.dialect.Oracle9Dialect

      Sybase

      org.hibernate.dialect.SybaseDialect

      Sybase Anywhere

      org.hibernate.dialect.SybaseAnywhereDialect

      Microsoft SQL Server

      org.hibernate.dialect.SQLServerDialect

      SAP DB

      org.hibernate.dialect.SAPDBDialect

      Informix

      org.hibernate.dialect.InformixDialect

      HypersonicSQL

      org.hibernate.dialect.HSQLDialect

      属性名

      描??? 述

      Ingres

      org.hibernate.dialect.IngresDialect

      Progress

      org.hibernate.dialect.ProgressDialect

      Mckoi SQL

      org.hibernate.dialect.MckoiDialect

      Interbase

      org.hibernate.dialect.InterbaseDialect

      Pointbase

      org.hibernate.dialect.PointbaseDialect

      示例如下:

      除了前面几节列举的配置外,Hibernate的JPA实现还有一些常用的配置,如下所示。

      属性名:hibernate.show_sql

      描述:是否输出SQL语句。

      可选值:

      true(默认):输出SQL,相当于日志中设置org.hibernate.SQL的类别值为debug。

      false:不输出SQL。

      示例如下:

      属性名:hibernate.default_schema

      描述:生成的SQL默认的schema名称。

      示例如下:

      <property name="hibernate.default_schema"? value="test"/>

      属性名:hibernate.default_catalog

      描述:生成的SQL默认的catalog名称。

      示例如下:

      <property name="hibernate.default_catalog"? value="test"/>

      属性名:hibernate.max_fetch_depth

      描述:一对一和多对一映射时,实体加载的最大深度,0表示不抓取相关实体。建议值在0~3之间,默认为1。

      示例如下:

      <property name="hibernate.max_fetch_depth"? value="2"/>

      属性名:hibernate.default_batch_fetch_size

      描述:加载相关联的实体集合时,所加载的相关实体个数。建议使用2的倍数值,例如4、8(默认)、16。

      示例如下:

      <property name="hibernate.default_batch_fetch_size"? value="16"/>

      大多数情况下,Hibernate JPA中使用默认的设置就能基本满足需求,但当需求变化时,需要进行一些特殊的优化时,就可以通过自定义的一些属性来实现目标。

      1 楼 letmedown 2012-05-11 你好,请问一个问题.
      在以下代码中:
      9.一对一映射关系
      主Pojo

      @Entity
      @Table(name = "T_ONEA")
      public class OneA implements Serializable {
      ..............
      .............
      private OneB oneB;
      }
      OneA对象有一个OneB类型的成员变量.JPA要求oneB的字面类型必须是OneB类型.而不能是OneB实现的接口,或OneB的父类.这与面向接口编码有一点不符合.
      请问,在程序的业务模块中如何更好地引用OneA与OneB等业务对象.来进行向面接口设计?
      我的想法是:业务对象OneA,OneB等主要的职责是在JPA的管理下与数据交互,从数据库取数据或存数据.业务操作是由其他接口(接口的实现)实现的.例如:
      public interface IOneABiz{
      void bizMethodA(IOneA oneA);//业务操作时可以而向接口编程
      void bizMethodB(IOneB oneB);
      }
      public class OneABiz implements IOneBiz{
      .............
      .............
      }
      OneA与OneB都应该有自己的接口(接口中的方法可能只是getter setter方法)
      public interface IOneA{
      void setOneB(OneB oneB);
      OneB getOneB();
      }
      public interface IOneB{
      ..................
      ....................
      }
      业务对象应该实现自己的接口

      @Entity
      @Table(name = "T_ONEA")
      public class OneA implements Serializable, IOneA {
      ..............
      .............
      private OneB oneB;//这里为了欺骗JPA对象的字面类型还是使用具体类型,而不是IOneB
      }
      @Entity
      @Table(name = "T_ONEB")
      public class OneB implements Serializable, IOneB{
      ...................
      ...................
      }
      总结:
      这样的话在JPA中为了欺骗JPA成员变量的字面类型还是使用具体类型,而不是接口.而/业务操作时可以而向接口编程.


      2 楼 handawei 2012-06-18 有道理,jpa是orm框架的java标准,它关注的是对象到关系的全映射,要想在业务中实现面向接口的编程,可以额外添加接口.

读书人网 >行业软件

热点推荐