翻译自 Hibernate Annotations
2. 映射简单的属性
2.1.声明基本的属性映射
每个非静态非瞬态属性(取决于访问类型的字段或方法)都被认为是持久性的,除非您将其注释为@Transient。没有为您的财产注释等同于适当的 @Basic注释。该@Basic 注释允许您声明属性的获取策略:
public transient int counter; //transient propertyprivate String firstname; //persistent property@Transient
String getLengthInMeter() { ... } //transient propertyString getName() {... } // persistent property@Basic
int getLength() { ... } // persistent property@Basic(fetch = FetchType.LAZY)
String getDetailedComment() { ... } // persistent property@Temporal(TemporalType.TIME)
java.util.Date getDepartureTime() { ... } // persistent property @Enumerated(EnumType.STRING)
Starred getNote() { ... } //enum persisted as String in database
counter,一个瞬时字段,以及 lengthInMeter注释为@Transient实体管理器并且将被实体管理器忽略的方法 。name,length和 firstname属性被映射为持久且急切地获取(简单属性的默认值)。在 detailedComment一次实体的懒属性是第一次访问属性值将延迟访从数据库中。通常你不需要懒惰的简单属性(不要与懒惰的关联抓取相混淆)。
注意:
为了启用属性级别的延迟获取,必须对类进行检测:将字节码添加到原始类中以启用此类功能,请参阅Hibernate参考文档。如果你的类没有插装,属性级别的延迟加载会被忽略。
推荐的替代方法是使用JP-QL(Java持久性查询语言)或Criteria查询的投影功能。
JPA支持Hibernate支持的所有基本类型(所有基本Java类型,它们各自的包装器和可序列化类)的属性映射。Hibernate Annotations支持开箱枚举类型映射到有序列(保存枚举序列)或基于字符串的列(保存枚举字符串表示形式):默认为序号的 持久性表示可以通过@Enumerated 注释覆盖,如图所示在note属性的例子。
在普通的Java API中,时间的时间精度没有被定义。在处理时态数据时,您可能想要描述数据库中的预期精度。时间数据可以具有 DATE,TIME或 TIMESTAMP精确(即实际日期,只有时间或两者)。使用@Temporal注释来微调。
@Lob表示该属性应该以斑点或者根据属性类型的Clob被保留: java.sql.Clob, Character[],char[]和的java.lang。String将坚持在Clob。 java.sql.Blob,Byte[], byte[] 和序列化的类型将被在一个斑点持续存在。
@ Lob
public String getFullText (){ return fullText ; } @ Lob public byte [] getFullCode (){ return fullCode ; }
如果属性类型实现 java.io.Serializable并且不是基本类型,并且该属性未被注释@Lob,则使用Hibernate serializable类型。
2.2.访问类型
注解在类层次结构中的放置必须一致(字段或属性)才能确定默认访问类型。建议在整个应用程序中坚持使用单个注释放置策略。
但是在某些情况下,您需要:
- 强制实体层次结构的访问类型
- 覆盖类层次结构中特定实体的访问类型
- 覆盖可嵌入类型的访问类型
要强制给定类的访问类型,请使用@Access如下所示的 注释:
@Entity
public class Order {@Id private Long id;public Long getId() { return id; }public void setId(Long id) { this.id = id; }@Embedded private Address address;public Address getAddress() { return address; }public void setAddress() { this.address = address; }
}@Entity
public class User {private Long id;@Id public Long getId() { return id; }public void setId(Long id) { this.id = id; }private Address address;@Embedded public Address getAddress() { return address; }public void setAddress() { this.address = address; }
}@Embeddable
@Access(AcessType.PROPERTY)
public class Address {private String street1;public String getStreet1() { return street1; }public void setStreet1() { this.street1 = street1; }private hashCode; //not persistent
}
您还可以覆盖单个属性的访问类型,同时保持其他属性的标准。
@Entity
public class Order {@Id private Long id;public Long getId() { return id; }public void setId(Long id) { this.id = id; }@Transient private String userId;@Transient private String orderId;@Access(AccessType.PROPERTY)public String getOrderNumber() { return userId + ":" + orderId; }public void setOrderNumber() { this.userId = ...; this.orderId = ...; }
}
在此示例中,默认访问类型 FIELD除 orderNumber属性外。请注意,相应的字段(如果有)必须标记为@Transient或 transient。
@ org.hibernate.annotations.AccessType
@org.hibernate.annotations.AccessType对于FIELD和PROPERTY访问,该注释 应被视为弃用。但是,如果您需要使用自定义访问类型,它仍然很有用。
2.3. 声明列属性
可以使用@Column注释来定义用于属性映射的列。使用它来覆盖默认值(有关默认值的更多信息,请参阅EJB3规范)。您可以在属性级别对此属性使用此注释:
- 根本没有注释
- 注释 @Basic
- 注释 @Version
- 注释 @Lob
- 注释 @Temporal
@Entity
public class Flight implements Serializable {
...
@Column(updatable = false, name = "flight_name", nullable = false, length=50)
public String getName() { ... }
该name属性映射到flight_name不可空的 列,长度为50,不可更新(使属性不可变)。
该注释可以应用于常规的性质以及 @Id或@Version 性质。
@Column(name="colu(1)mnName";boolean un(2)ique() default false;boolean nu(3)llable() default true;boolean in(4)sertable() default true;boolean up(5)datable() default true;String col(6)umnDefinition() default "";String tab(7)le() default "";int length(8)() default 255;int precis(9)ion() default 0; // decimal precisionint scale((10)) default 0; // decimal scale
name (可选):列名称(默认为属性名称)
unique (可选):是否在此列上设置唯一约束(默认为false)
nullable (可选):将列设置为可空(默认为true)。
insertable (可选):列是否将成为插入语句的一部分(默认为true)
updatable (可选):列是否将成为更新语句的一部分(默认为true)
columnDefinition (可选):覆盖此特定列的sql DDL片段(非便携式)
table (可选):定义目标表(默认主表)
length (可选):列长度(默认值为255)
precision (可选):列小数精度(默认值为0)
scale (可选):十进制小数点(如果有用的话)(默认值为0)
2.4. 嵌入式对象(又名组件)
可以在实体内部声明一个嵌入式组件,甚至可以覆盖它的列映射。组件类必须用注解在类级别进行@Embeddable 注释。可以使用 相关属性中的@Embedded和@AttributeOverride注释来覆盖特定实体的嵌入对象的列映射 :
@Entity
public class Person implements Serializable {// Persistent component using defaultsAddress homeAddress;@Embedded@AttributeOverrides( {@AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),@AttributeOverride(name="name", column = @Column(name="bornCountryName") )} )Country bornIn;...
}
@Embeddable
public class Address implements Serializable {String city;Country nationality; //no overriding here
}
@Embeddable
public class Country implements Serializable {private String iso2;@Column(name="countryName") private String name;public String getIso2() { return iso2; }public void setIso2(String iso2) { this.iso2 = iso2; }public String getName() { return name; }public void setName(String name) { this.name = name; }...
}
可嵌入对象继承其拥有实体的访问类型(请注意,您可以使用@Access注释覆盖该类型 )。
该Person实体具有两个组件属性,homeAddress并且 bornIn。homeAddress属性没有被注解,但Hibernate会通过@Embeddable在Address类中查找注释来猜测它是一个持久组件。我们还覆盖列名的映射(以bornCountryName与所述) @Embedded和@AttributeOverride 注解的每个映射属性 Country。正如你所看到的,Country 它也是一个嵌套的组件Address,同样使用Hibernate和JPA默认的自动检测。覆盖嵌入对象嵌入对象的列是通过虚线表达式。
@Embedded@AttributeOverrides( {@AttributeOverride(name="city", column = @Column(name="fld_city") ),@AttributeOverride(name="nationality.iso2", column = @Column(name="nat_Iso2") ),@AttributeOverride(name="nationality.name", column = @Column(name="nat_CountryName") )//nationality columns in homeAddress are overridden} )Address homeAddress;
Hibernate Annotations支持JPA规范没有明确支持的东西。您可以使用注释对嵌入对象进行@MappedSuperclass注释,以使超类属性保持不变(请参阅 @MappedSuperclass以获取更多信息)。
您还可以使用关联标注在嵌入对象(即@OneToOne,@ManyToOne, @OneToMany或@ManyToMany)。覆盖您可以使用的关联列 @AssociationOverride。
如果您希望在同一实体中具有相同的可嵌入对象类型两次,则列名默认将不起作用,因为多个嵌入对象将共享同一组列。在普通的JPA中,您需要覆盖至少一组列。然而,Hibernate允许你通过NamingStrategy界面增强默认的命名机制 。你可以写一个策略来防止名称在这种情况下发生冲突。 DefaultComponentSafeNamingStrategy就是这样一个例子。
2.5.未注释的属性默认值
如果一个财产没有注释,则适用下列规则:
- 如果该属性属于单一类型,则将其映射为@Basic
- 否则,如果该属性的类型被注释为@Embeddable,则它被映射为@Embedded
- 否则,如果该属性的类型是 Serializable,则将其映射为 @Basic保存该序列化版本中的对象的列
- 否则,如果该属性的类型是 java.sql.Clob或 java.sql.Blob,则将其映射为 @Lob适当的 LobType