Hibernate对Annotation的扩展
Hibernate 3.1 提供了多种附加的注解,这些注解可以与EJB3的实体混合/匹配使用。
他们被设计成EJB3注解的自然扩展。
To empower the EJB3 capabilities, hibernate provides specific
annotations that match hibernate features. The
org.hibernate.annotations package contains all
these annotations extensions.
为了强化EJB3的能力,Hibernate提供了与其自身特性相吻合的特殊注解。
org.hibernate.annotations包已包含了所有的这些注解扩展。
Entity
You can fine tune some of the actions done by Hibernate on
entities beyond what the EJB3 spec offers.
你可以在EJB3规范所能提供的能力之外,就Hibernate对实体所作的一些操作进行优化。
@org.hibernate.annotations.Entity adds
additional metadata that may be needed beyond what is defined in the
standard @Entity
mutable: whether this entity is mutable or not
dynamicInsert: allow dynamic SQL for inserts
dynamicUpdate: allow dynamic SQL for updates
selectBeforeUpdate: Specifies that Hibernate should never perform an SQL UPDATE unless it is certain that an object is actually modified.
polymorphism: whether the entity polymorphism is of PolymorphismType.IMPLICIT (default) or PolymorphismType.EXPLICIT
persister: allow the overriding of the default persister implementation
optimisticLock: optimistic locking strategy (OptimisticLockType.VERSION, OptimisticLockType.NONE, OptimisticLockType.DIRTY or OptimisticLockType.ALL)
@org.hibernate.annotations.Entity
追加了可能需要的额外的元数据,
而这些元数据超出了标准@Entity 中所定义的元数据。
mutable: 此实体是否为可变的
dynamicInsert: 用动态SQL新增
dynamicUpdate: 用动态SQL更新
selectBeforeUpdate: 指明Hibernate从不运行SQL UPDATE除非能确定对象的确已被修改
polymorphism: (指出)实体多态是PolymorphismType.IMPLICIT(默认)还是PolymorphismType.EXPLICIT
persister: allow the overriding of the default persister implementation
允许对默认持久实现(persister implementation)的覆盖
optimisticLock: 乐观锁策略(OptimisticLockType.VERSION, OptimisticLockType.NONE, OptimisticLockType.DIRTY 或 OptimisticLockType.ALL)
note
@javax.persistence.Entity is still mandatory,
@org.hibernate.annotations.Entity is not a replacement.
note
@javax.persistence.Entity仍是必选的(mandatory),
@org.hibernate.annotations.Entity不是取代品。
Here are some additional Hibernate annotation extensions
以下是一些附加的Hibernate注解扩展:
@org.hibernate.annotations.BatchSize allows you
to define the batch size when fetching instances of this entity ( eg.
@BatchSize(size=4) ). When loading a given entity,
Hibernate will then load all the uninitialized entities of the same type
in the persistence context up to the batch size.
@org.hibernate.annotations.BatchSize 允许你定义批量抓取该实体的实例数量(如:@BatchSize(size=4))。
当加载一特定的实体时,Hibernate将加载在持久上下文中未经初始化的同类型实体,直至批量数量(上限)。
@org.hibernate.annotations.Proxy defines the
laziness attributes of the entity. lazy (default to true) define whether
the class is lazy or not. proxyClassName is the interface used to
generate the proxy (default is the class itself).
@org.hibernate.annotations.Proxy
定义了实体的延迟属性。Lazy(默认为true)定义了类是否为延迟(加载)。
proxyClassName是用来生成代理的接口(默认为该类本身)。
@org.hibernate.annotations.Where defines an
optional SQL WHERE clause used when instances of this class is
retrieved.
@org.hibernate.annotations.Where定义了当获取类实例时所用的SQL WHERE子句(该SQL WHERE子句为可选)。
@org.hibernate.annotations.Check defines an
optional check constraints defined in the DDL statetement.
@org.hibernate.annotations.Check
定义了在DDL语句中定义的合法性检查约束(该约束为可选)。
@OnDelete(action=OnDeleteAction.CASCADE) on
joined subclasses: use a SQL cascade delete on deletion instead of the
regular Hibernate mechanism.
@OnDelete(action=OnDeleteAction.CASCADE)
定义于被连接(joined)的子类:在删除时使用SQL级连删除,而非通常的Hibernate删除机制。
@Table(name="tableName", indexes = {
@Index(name="index1", columnNames={"column1", "column2"} ) } )
creates the defined indexes on the columns of table tableName. This can
be applied on the primary table or any secondary table. The
@Tables annotation allows your to apply indexes on
different tables. This annotation is expected where
@javax.persistence.Table or
@javax.persistence.SecondaryTable(s) occurs.
@org.hibernate.annotations.Table is a complement, not
a replacement to @javax.persistence.Table
@Table(name="tableName", indexes = {
@Index(name="index1", columnNames={"column1", "column2"} ) } )在tableName表的字段上创建定义好的索引。该注解可以被应用于关键表或者是其他次要的表。
@Tables 注解允许你在不同的表上应用索引。
此注解预期在使用
@javax.persistence.Table或
@javax.persistence.SecondaryTable的地方中出现.
@org.hibernate.annotations.Table 是对
@javax.persistence.Table的补充而不是它的替代品。
programlisting
@Entity
@BatchSize(size=5)
@org.hibernate.annotations.Entity(
selectBeforeUpdate = true,
dynamicInsert = true, dynamicUpdate = true,
optimisticLock = OptimisticLockType.ALL,
polymorphism = PolymorphismType.EXPLICIT)
@Where(clause="1=1")
@org.hibernate.annotations.Table(name="Forest", indexes = { @Index(name="idx", columnNames = { "name", "length" } ) } )
public class Forest { ... }
programlisting
@Entity
@Inheritance(
strategy=InheritanceType.JOINED
)
public class Vegetable { ... }
@Entity
@OnDelete(action=OnDeleteAction.CASCADE)
public class Carrot extends Vegetable { ... }
Identifier
@org.hibernate.annotations.GenericGenerator
allows you to define an Hibernate specific id
generator.
@org.hibernate.annotations.GenericGenerator
允许你定义一个Hibernate特定的id生成器。
programlisting
@Id @GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
public String getId() {
@Id @GeneratedValue(generator="hibseq")
@GenericGenerator(name="hibseq", strategy = "seqhilo",
parameters = {
@Parameter(name="max_lo", value = "5"),
@Parameter(name="sequence", value="heybabyhey")
}
)
public Integer getId() {
strategy is the short name of an Hibernate3
generator strategy or the fully qualified class name of an
IdentifierGenerator implementation. You can add
some parameters through the parameters
attribute
strategy可以是Hibernate3生成器策略的简称,或者是一个IdentifierGenerator实现的(带包路径的)全限定类名。
你可以通过parameters属性增加一些参数。
Property
Access type
The access type is guessed from the position of
@Id or @EmbeddedId in the entity
hierarchy. Sub-entities, embedded objects and mapped superclass
inherit the access type from the root entity.
访问类型是根据@Id或@EmbeddedId在实体继承层次中所处的位置推演而得的。子实体(Sub-entities),内嵌对象和被映射的父类均从根实体(root entity)继承访问类型。
In Hibernate, you can override the access type to:
在Hibernate中,你可以把访问类型覆盖成:
use a custom access type strategy
fine tune the access type at the class level or at the
property level
使用定制的访问类型策略
优化类级别或属性级别的访问类型
An @AccessType annotation has been introduced to support this
behavior. You can define the access type on
为支持这种行为,Hibernate引入了@AccessType注解。你可以对以下元素定义访问类型:
an entity
a superclass
an embeddable object
a property
实体
父类
可内嵌的对象
属性
The access type is overriden for the annotated element, if
overriden on a class, all the properties of the given class inherit
the access type. For root entities, the access type is considered to
be the default one for the whole hierarchy (overridable at class or
property level).
被注解元素的访问类型会被覆盖,若覆盖是在类级别上,则所有的属性继承访问类型。
对于根实体,其访问类型会被认为是整个继承层次中的缺省设置(可在类或属性一级覆盖)。
If the access type is marked as "property", the getters are
scanned for annotations, if the access type is marked as "field", the
fields are scanned for annotations. Otherwise the elements marked with
@Id or @embeddedId are scanned.
若访问类型被标以"property",则Hibernate会扫描getter方法的注解,若访问类型被标以"field",则扫描字段的注解。否则,扫描标为@Id或@embeddedId的元素。
You can override an access type for a property, but the element
to annotate will not be influenced: for example an entity having
access type field, can annotate a field with
@AccessType("property"), the access type will then
be property for this attribute, the the annotations still have to be
carried on the field.
你可以覆盖某个属性(property)的访问类型,但是受注解的元素将不受影响:例如一个具有field访问类型的实体,(我们)可以将某个字段标注为 @AccessType("property"),则该字段的访问类型随之将成为property,但是其他字段上依然需要携带注解。
If a superclass or an embeddable object is not annotated, the
root entity access type is used (even if an access type has been
define on an intermediate superclass or embeddable object). The
russian doll principle does not apply.
若父类或可内嵌的对象没有被注解,则使用根实体的访问类型(即使已经在非直系父类或可内嵌对象上定义了访问类型)。此时俄罗斯套娃(Russian doll)原理就不再适用。(译注:俄罗斯套娃(матрёшка或 матрешка)是俄罗斯特产木制玩具,一般由多个一样图案的空心木娃娃一个套一个组成,最多可达十多个,通常为圆柱形,底部平坦可以直立。)
programlisting
@Entity
public class Person implements Serializable {
@Id @GeneratedValue //access type field
Integer id;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "iso2", column = @Column(name = "bornIso2")),
@AttributeOverride(name = "name", column = @Column(name = "bornCountryName"))
})
Country bornIn;
}
@Embeddable
@AccessType("property") //override access type for all properties in Country
public class Country implements Serializable {
private String iso2;
private String name;
public String getIso2() {
return iso2;
}
public void setIso2(String iso2) {
this.iso2 = iso2;
}
@Column(name = "countryName")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Formula
Sometimes, you want the Database to do some computation for you
rather than in the JVM, you might also create some kind of virtual
column. You can use a SQL fragment (aka formula) instead of mapping a
property into a column. This kind of property is read only (its value
is calculated by your formula fragment).
Sometimes, you want the Database to do some computation for you
rather than in the JVM, you might also create some kind of virtual
column. You can use a SQL fragment (aka formula) instead of mapping a
property into a column. This kind of property is read only (its value
is calculated by your formula fragment).
有时候,你想让数据库,而非JVM,来替你完成一些计算,也可能想创建某种虚拟字段(译注:即数据库视图)。你可以使用一段SQL(亦称为公式),而不是将属性映射到(物理)字段。 这种属性是只读的(属性值由公求得)。
programlisting
@Formula("obj_length * obj_height * obj_width")
public long getObjectVolume()
The SQL fragment can be as complex as you want avec even include
subselects.
SQL片段可以是任意复杂的,甚至可包含子查询。
Type
@org.hibernate.annotations.Type overrides the
default hibernate type used: this is generally not necessary since the
type is correctly inferred by Hibernate. Please refer to the Hibernate
reference guide for more informations on the Hibernate types.
@org.hibernate.annotations.Type
覆盖了Hibernate所用的默认类型:这通常不是必须的,因为类型可以由Hibernate正确推得。
关于Hibernate类型的详细信息,请参考Hibernate使用手册。
@org.hibernate.annotations.TypeDef and
@org.hibernate.annotations.TypeDefs allows you to
declare type definitions. These annotations are placed at the class or
package level. Note that these definitions will be global for the
session factory (even at the class level) and that type definition has
to be defined before any usage.
@org.hibernate.annotations.TypeDef 和
@org.hibernate.annotations.TypeDefs允许你来声明类型定义。
这些注解被置于类或包一级。注意,对session factory来说,
这些定义将是全局的(即使定义于类一级),并且类型定义必须先于任何使用。
programlisting
@TypeDefs(
{
@TypeDef(
name="caster",
typeClass = CasterStringType.class,
parameters = {
@Parameter(name="cast", value="lower")
}
)
}
)
package org.hibernate.test.annotations.entity;
...
public class Forest {
@Type(type="caster")
public String getSmallText() {
...
}
When using composite user type, you will have to express column
definitions. The @Columns has been introduced for
that purpose.
当使用组合的用户自定义类型时,你必须自己来表达字段定义。
@Columns就是为了此目的而引入的。
programlisting
@Type(type="org.hibernate.test.annotations.entity.MonetaryAmountUserType")
@Columns(columns = {
@Column(name="r_amount"),
@Column(name="r_currency")
})
public MonetaryAmount getAmount() {
return amount;
}
public class MonetaryAmount implements Serializable {
private BigDecimal amount;
private Currency currency;
...
}
Index
You can define an index on a particular column using the
@Index annotation on a one column property, the
columnNames attribute will then be ignored
通过在字段属性(property)上使用@Index注解,
可以在特定字段上定义索引,columnNames属性(attribute)将随之被忽略。
programlisting
@Column(secondaryTable="Cat1")
@Index(name="story1index")
public String getStoryPart1() {
return storyPart1;
}
Inheritance
SINGLE_TABLE is a very powerful strategy but sometimes, and
especially for legacy systems, you cannot add an additional
discriminator column. For that purpose Hibernate has introduced the
notion of discriminator formula:
@DiscriminatorFormula is a replacement of
@DiscriminatorColumn and use a SQL fragment as a
formula for discriminator resolution (no need to have a dedicated
column).
SINGLE_TABLE 是个功能强大的策略,但有时,特别对遗留系统而言,
是无法加入一个额外的识别符字段(discriminator column)。
由此,Hibernate引入了识别符公式(discriminator formula)的概念:
@DiscriminatorFormula是@DiscriminatorColumn的替代品,
它使用SQL片段作为识别符解决方案的公式( 不需要有一个专门的字段)。
programlisting
@Entity
@DiscriminatorForumla("case when forest_type is null then 0 else forest_type end")
public class Forest { ... }
Association related annotations
By default, when Hibernate cannot resolve the association because
the expected associated element is not in database (wrong id on the
association column), an exception is raised by Hibernate. This might be
inconvenient for lecacy and badly maintained schemas. You can ask
Hibernate to ignore such elements instead of raising an exception using
the @NotFound annotation. This annotation can be used
on a @OneToOne (with FK),
@ManyToOne, @OneToMany or
@ManyToMany association.
默认情况下,当预期的被关联元素不在数据库中(关乎关联字段的id错误),致使Hiberante无法解决关联性问题时,Hibernate就会抛出异常。
这对遗留schema和历经拙劣维护的schema而言,这或有许多不便。
此时,你可用 @NotFound 注解让Hibernate略过这样的元素而不是抛出异常。
该注解可用于 @OneToOne (有外键)、 @ManyToOne 、
@OneToMany 或 @ManyToMany 关联。
programlisting
@Entity
public class Child {
...
@ManyToOne
@NotFound(action=NotFoundAction.IGNORE)
public Parent getParent() { ... }
...
}
Collection related annotations
Parameter annotations
It is possible to set
the batch size for collections using @BatchSize
the where clause, using @Where
the check clause, using @Check
the SQL order by clause, using @OrderBy
the delete cascade strategy through @OnDelete(action=OnDeleteAction.CASCADE)
以下是可能的设置方式
用@BatchSizebatch设置集合的batch大小
用@Where注解设置Where子句
用注解@Check来设置check子句
用注解@OrderBy来设置SQL的order by子句
利用@OnDelete(action=OnDeleteAction.CASCADE) 注解设置级连删除策略
You can also declare a sort comparator. Use the
@Sort annotation. Expressing the comparator type
you want between unsorted, natural or custom comparator. If you want
to use your own comparator implementation, you'll also have to express
the implementation class using the comparator
attribute.
你也可以利用@Sort注解定义一个排序比较器(sort comparator),表明希望的比较器类型,无序、自然顺序或自定义排序,三者择一。若你想用你自己实现的comparator,
你还需要利用comparator属性(attribute)指明实现类。
programlisting
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@Sort(type = SortType.COMPARATOR, comparator = TicketComparator.class)
@Where(clause="1=1")
@OnDelete(action=OnDeleteAction.CASCADE)
public SortedSet<Ticket> getTickets() {
return tickets;
}
他们被设计成EJB3注解的自然扩展。
To empower the EJB3 capabilities, hibernate provides specific
annotations that match hibernate features. The
org.hibernate.annotations package contains all
these annotations extensions.
为了强化EJB3的能力,Hibernate提供了与其自身特性相吻合的特殊注解。
org.hibernate.annotations包已包含了所有的这些注解扩展。
Entity
You can fine tune some of the actions done by Hibernate on
entities beyond what the EJB3 spec offers.
你可以在EJB3规范所能提供的能力之外,就Hibernate对实体所作的一些操作进行优化。
@org.hibernate.annotations.Entity adds
additional metadata that may be needed beyond what is defined in the
standard @Entity
mutable: whether this entity is mutable or not
dynamicInsert: allow dynamic SQL for inserts
dynamicUpdate: allow dynamic SQL for updates
selectBeforeUpdate: Specifies that Hibernate should never perform an SQL UPDATE unless it is certain that an object is actually modified.
polymorphism: whether the entity polymorphism is of PolymorphismType.IMPLICIT (default) or PolymorphismType.EXPLICIT
persister: allow the overriding of the default persister implementation
optimisticLock: optimistic locking strategy (OptimisticLockType.VERSION, OptimisticLockType.NONE, OptimisticLockType.DIRTY or OptimisticLockType.ALL)
@org.hibernate.annotations.Entity
追加了可能需要的额外的元数据,
而这些元数据超出了标准@Entity 中所定义的元数据。
mutable: 此实体是否为可变的
dynamicInsert: 用动态SQL新增
dynamicUpdate: 用动态SQL更新
selectBeforeUpdate: 指明Hibernate从不运行SQL UPDATE除非能确定对象的确已被修改
polymorphism: (指出)实体多态是PolymorphismType.IMPLICIT(默认)还是PolymorphismType.EXPLICIT
persister: allow the overriding of the default persister implementation
允许对默认持久实现(persister implementation)的覆盖
optimisticLock: 乐观锁策略(OptimisticLockType.VERSION, OptimisticLockType.NONE, OptimisticLockType.DIRTY 或 OptimisticLockType.ALL)
note
@javax.persistence.Entity is still mandatory,
@org.hibernate.annotations.Entity is not a replacement.
note
@javax.persistence.Entity仍是必选的(mandatory),
@org.hibernate.annotations.Entity不是取代品。
Here are some additional Hibernate annotation extensions
以下是一些附加的Hibernate注解扩展:
@org.hibernate.annotations.BatchSize allows you
to define the batch size when fetching instances of this entity ( eg.
@BatchSize(size=4) ). When loading a given entity,
Hibernate will then load all the uninitialized entities of the same type
in the persistence context up to the batch size.
@org.hibernate.annotations.BatchSize 允许你定义批量抓取该实体的实例数量(如:@BatchSize(size=4))。
当加载一特定的实体时,Hibernate将加载在持久上下文中未经初始化的同类型实体,直至批量数量(上限)。
@org.hibernate.annotations.Proxy defines the
laziness attributes of the entity. lazy (default to true) define whether
the class is lazy or not. proxyClassName is the interface used to
generate the proxy (default is the class itself).
@org.hibernate.annotations.Proxy
定义了实体的延迟属性。Lazy(默认为true)定义了类是否为延迟(加载)。
proxyClassName是用来生成代理的接口(默认为该类本身)。
@org.hibernate.annotations.Where defines an
optional SQL WHERE clause used when instances of this class is
retrieved.
@org.hibernate.annotations.Where定义了当获取类实例时所用的SQL WHERE子句(该SQL WHERE子句为可选)。
@org.hibernate.annotations.Check defines an
optional check constraints defined in the DDL statetement.
@org.hibernate.annotations.Check
定义了在DDL语句中定义的合法性检查约束(该约束为可选)。
@OnDelete(action=OnDeleteAction.CASCADE) on
joined subclasses: use a SQL cascade delete on deletion instead of the
regular Hibernate mechanism.
@OnDelete(action=OnDeleteAction.CASCADE)
定义于被连接(joined)的子类:在删除时使用SQL级连删除,而非通常的Hibernate删除机制。
@Table(name="tableName", indexes = {
@Index(name="index1", columnNames={"column1", "column2"} ) } )
creates the defined indexes on the columns of table tableName. This can
be applied on the primary table or any secondary table. The
@Tables annotation allows your to apply indexes on
different tables. This annotation is expected where
@javax.persistence.Table or
@javax.persistence.SecondaryTable(s) occurs.
@org.hibernate.annotations.Table is a complement, not
a replacement to @javax.persistence.Table
@Table(name="tableName", indexes = {
@Index(name="index1", columnNames={"column1", "column2"} ) } )在tableName表的字段上创建定义好的索引。该注解可以被应用于关键表或者是其他次要的表。
@Tables 注解允许你在不同的表上应用索引。
此注解预期在使用
@javax.persistence.Table或
@javax.persistence.SecondaryTable的地方中出现.
@org.hibernate.annotations.Table 是对
@javax.persistence.Table的补充而不是它的替代品。
programlisting
@Entity
@BatchSize(size=5)
@org.hibernate.annotations.Entity(
selectBeforeUpdate = true,
dynamicInsert = true, dynamicUpdate = true,
optimisticLock = OptimisticLockType.ALL,
polymorphism = PolymorphismType.EXPLICIT)
@Where(clause="1=1")
@org.hibernate.annotations.Table(name="Forest", indexes = { @Index(name="idx", columnNames = { "name", "length" } ) } )
public class Forest { ... }
programlisting
@Entity
@Inheritance(
strategy=InheritanceType.JOINED
)
public class Vegetable { ... }
@Entity
@OnDelete(action=OnDeleteAction.CASCADE)
public class Carrot extends Vegetable { ... }
Identifier
@org.hibernate.annotations.GenericGenerator
allows you to define an Hibernate specific id
generator.
@org.hibernate.annotations.GenericGenerator
允许你定义一个Hibernate特定的id生成器。
programlisting
@Id @GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
public String getId() {
@Id @GeneratedValue(generator="hibseq")
@GenericGenerator(name="hibseq", strategy = "seqhilo",
parameters = {
@Parameter(name="max_lo", value = "5"),
@Parameter(name="sequence", value="heybabyhey")
}
)
public Integer getId() {
strategy is the short name of an Hibernate3
generator strategy or the fully qualified class name of an
IdentifierGenerator implementation. You can add
some parameters through the parameters
attribute
strategy可以是Hibernate3生成器策略的简称,或者是一个IdentifierGenerator实现的(带包路径的)全限定类名。
你可以通过parameters属性增加一些参数。
Property
Access type
The access type is guessed from the position of
@Id or @EmbeddedId in the entity
hierarchy. Sub-entities, embedded objects and mapped superclass
inherit the access type from the root entity.
访问类型是根据@Id或@EmbeddedId在实体继承层次中所处的位置推演而得的。子实体(Sub-entities),内嵌对象和被映射的父类均从根实体(root entity)继承访问类型。
In Hibernate, you can override the access type to:
在Hibernate中,你可以把访问类型覆盖成:
use a custom access type strategy
fine tune the access type at the class level or at the
property level
使用定制的访问类型策略
优化类级别或属性级别的访问类型
An @AccessType annotation has been introduced to support this
behavior. You can define the access type on
为支持这种行为,Hibernate引入了@AccessType注解。你可以对以下元素定义访问类型:
an entity
a superclass
an embeddable object
a property
实体
父类
可内嵌的对象
属性
The access type is overriden for the annotated element, if
overriden on a class, all the properties of the given class inherit
the access type. For root entities, the access type is considered to
be the default one for the whole hierarchy (overridable at class or
property level).
被注解元素的访问类型会被覆盖,若覆盖是在类级别上,则所有的属性继承访问类型。
对于根实体,其访问类型会被认为是整个继承层次中的缺省设置(可在类或属性一级覆盖)。
If the access type is marked as "property", the getters are
scanned for annotations, if the access type is marked as "field", the
fields are scanned for annotations. Otherwise the elements marked with
@Id or @embeddedId are scanned.
若访问类型被标以"property",则Hibernate会扫描getter方法的注解,若访问类型被标以"field",则扫描字段的注解。否则,扫描标为@Id或@embeddedId的元素。
You can override an access type for a property, but the element
to annotate will not be influenced: for example an entity having
access type field, can annotate a field with
@AccessType("property"), the access type will then
be property for this attribute, the the annotations still have to be
carried on the field.
你可以覆盖某个属性(property)的访问类型,但是受注解的元素将不受影响:例如一个具有field访问类型的实体,(我们)可以将某个字段标注为 @AccessType("property"),则该字段的访问类型随之将成为property,但是其他字段上依然需要携带注解。
If a superclass or an embeddable object is not annotated, the
root entity access type is used (even if an access type has been
define on an intermediate superclass or embeddable object). The
russian doll principle does not apply.
若父类或可内嵌的对象没有被注解,则使用根实体的访问类型(即使已经在非直系父类或可内嵌对象上定义了访问类型)。此时俄罗斯套娃(Russian doll)原理就不再适用。(译注:俄罗斯套娃(матрёшка或 матрешка)是俄罗斯特产木制玩具,一般由多个一样图案的空心木娃娃一个套一个组成,最多可达十多个,通常为圆柱形,底部平坦可以直立。)
programlisting
@Entity
public class Person implements Serializable {
@Id @GeneratedValue //access type field
Integer id;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "iso2", column = @Column(name = "bornIso2")),
@AttributeOverride(name = "name", column = @Column(name = "bornCountryName"))
})
Country bornIn;
}
@Embeddable
@AccessType("property") //override access type for all properties in Country
public class Country implements Serializable {
private String iso2;
private String name;
public String getIso2() {
return iso2;
}
public void setIso2(String iso2) {
this.iso2 = iso2;
}
@Column(name = "countryName")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Formula
Sometimes, you want the Database to do some computation for you
rather than in the JVM, you might also create some kind of virtual
column. You can use a SQL fragment (aka formula) instead of mapping a
property into a column. This kind of property is read only (its value
is calculated by your formula fragment).
Sometimes, you want the Database to do some computation for you
rather than in the JVM, you might also create some kind of virtual
column. You can use a SQL fragment (aka formula) instead of mapping a
property into a column. This kind of property is read only (its value
is calculated by your formula fragment).
有时候,你想让数据库,而非JVM,来替你完成一些计算,也可能想创建某种虚拟字段(译注:即数据库视图)。你可以使用一段SQL(亦称为公式),而不是将属性映射到(物理)字段。 这种属性是只读的(属性值由公求得)。
programlisting
@Formula("obj_length * obj_height * obj_width")
public long getObjectVolume()
The SQL fragment can be as complex as you want avec even include
subselects.
SQL片段可以是任意复杂的,甚至可包含子查询。
Type
@org.hibernate.annotations.Type overrides the
default hibernate type used: this is generally not necessary since the
type is correctly inferred by Hibernate. Please refer to the Hibernate
reference guide for more informations on the Hibernate types.
@org.hibernate.annotations.Type
覆盖了Hibernate所用的默认类型:这通常不是必须的,因为类型可以由Hibernate正确推得。
关于Hibernate类型的详细信息,请参考Hibernate使用手册。
@org.hibernate.annotations.TypeDef and
@org.hibernate.annotations.TypeDefs allows you to
declare type definitions. These annotations are placed at the class or
package level. Note that these definitions will be global for the
session factory (even at the class level) and that type definition has
to be defined before any usage.
@org.hibernate.annotations.TypeDef 和
@org.hibernate.annotations.TypeDefs允许你来声明类型定义。
这些注解被置于类或包一级。注意,对session factory来说,
这些定义将是全局的(即使定义于类一级),并且类型定义必须先于任何使用。
programlisting
@TypeDefs(
{
@TypeDef(
name="caster",
typeClass = CasterStringType.class,
parameters = {
@Parameter(name="cast", value="lower")
}
)
}
)
package org.hibernate.test.annotations.entity;
...
public class Forest {
@Type(type="caster")
public String getSmallText() {
...
}
When using composite user type, you will have to express column
definitions. The @Columns has been introduced for
that purpose.
当使用组合的用户自定义类型时,你必须自己来表达字段定义。
@Columns就是为了此目的而引入的。
programlisting
@Type(type="org.hibernate.test.annotations.entity.MonetaryAmountUserType")
@Columns(columns = {
@Column(name="r_amount"),
@Column(name="r_currency")
})
public MonetaryAmount getAmount() {
return amount;
}
public class MonetaryAmount implements Serializable {
private BigDecimal amount;
private Currency currency;
...
}
Index
You can define an index on a particular column using the
@Index annotation on a one column property, the
columnNames attribute will then be ignored
通过在字段属性(property)上使用@Index注解,
可以在特定字段上定义索引,columnNames属性(attribute)将随之被忽略。
programlisting
@Column(secondaryTable="Cat1")
@Index(name="story1index")
public String getStoryPart1() {
return storyPart1;
}
Inheritance
SINGLE_TABLE is a very powerful strategy but sometimes, and
especially for legacy systems, you cannot add an additional
discriminator column. For that purpose Hibernate has introduced the
notion of discriminator formula:
@DiscriminatorFormula is a replacement of
@DiscriminatorColumn and use a SQL fragment as a
formula for discriminator resolution (no need to have a dedicated
column).
SINGLE_TABLE 是个功能强大的策略,但有时,特别对遗留系统而言,
是无法加入一个额外的识别符字段(discriminator column)。
由此,Hibernate引入了识别符公式(discriminator formula)的概念:
@DiscriminatorFormula是@DiscriminatorColumn的替代品,
它使用SQL片段作为识别符解决方案的公式( 不需要有一个专门的字段)。
programlisting
@Entity
@DiscriminatorForumla("case when forest_type is null then 0 else forest_type end")
public class Forest { ... }
Association related annotations
By default, when Hibernate cannot resolve the association because
the expected associated element is not in database (wrong id on the
association column), an exception is raised by Hibernate. This might be
inconvenient for lecacy and badly maintained schemas. You can ask
Hibernate to ignore such elements instead of raising an exception using
the @NotFound annotation. This annotation can be used
on a @OneToOne (with FK),
@ManyToOne, @OneToMany or
@ManyToMany association.
默认情况下,当预期的被关联元素不在数据库中(关乎关联字段的id错误),致使Hiberante无法解决关联性问题时,Hibernate就会抛出异常。
这对遗留schema和历经拙劣维护的schema而言,这或有许多不便。
此时,你可用 @NotFound 注解让Hibernate略过这样的元素而不是抛出异常。
该注解可用于 @OneToOne (有外键)、 @ManyToOne 、
@OneToMany 或 @ManyToMany 关联。
programlisting
@Entity
public class Child {
...
@ManyToOne
@NotFound(action=NotFoundAction.IGNORE)
public Parent getParent() { ... }
...
}
Collection related annotations
Parameter annotations
It is possible to set
the batch size for collections using @BatchSize
the where clause, using @Where
the check clause, using @Check
the SQL order by clause, using @OrderBy
the delete cascade strategy through @OnDelete(action=OnDeleteAction.CASCADE)
以下是可能的设置方式
用@BatchSizebatch设置集合的batch大小
用@Where注解设置Where子句
用注解@Check来设置check子句
用注解@OrderBy来设置SQL的order by子句
利用@OnDelete(action=OnDeleteAction.CASCADE) 注解设置级连删除策略
You can also declare a sort comparator. Use the
@Sort annotation. Expressing the comparator type
you want between unsorted, natural or custom comparator. If you want
to use your own comparator implementation, you'll also have to express
the implementation class using the comparator
attribute.
你也可以利用@Sort注解定义一个排序比较器(sort comparator),表明希望的比较器类型,无序、自然顺序或自定义排序,三者择一。若你想用你自己实现的comparator,
你还需要利用comparator属性(attribute)指明实现类。
programlisting
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@Sort(type = SortType.COMPARATOR, comparator = TicketComparator.class)
@Where(clause="1=1")
@OnDelete(action=OnDeleteAction.CASCADE)
public SortedSet<Ticket> getTickets() {
return tickets;
}