- 浏览: 268022 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
xurun:
点击节点的时候出错,怎么办??1120行,data为空为或不是 ...
TreeGrid -
QQ371496669:
引用load方式检索不到的话会抛出org.hibernate. ...
Hibernate中No row with the given identifier exists -
汽车城路:
我现在正在使用这个Extjs,目前也遇到了这个问题,就是怎么换 ...
ext使用--Panel和iframe联合使用时页面高度的解决方法 -
jsjzhou:
有必要. 在实际项目我们就采用了HttpUrlConnecti ...
HttpURLConnection VS HttpClient性能测试 -
小猪笨笨:
不错,通俗易懂
在oracle中创建unique唯一约束(单列和多列)
有时候,你想让数据库,而非JVM,来替你完成一些计算,也可能想创建某种虚拟列.
你可以使用SQL片段(亦称为公式),而不是将属性映射到(物理)列. 这种属性是只读的(属性值由公求得).
@Formula("obj_length * obj_height * obj_width")
public long getObjectVolume()
SQL片段可以是任意复杂的,甚至可包含子查询.
@org.hibernate.annotations.Type
覆盖了Hibernate所用的默认类型:这通常不是必须的,因为类型可以由Hibernate正确推得.
关于Hibernate类型的详细信息,请参考Hibernate使用手册.
@org.hibernate.annotations.TypeDef 和@org.hibernate.annotations.TypeDefs允许你来声明类型定义.
这些注解被置于类或包一级.注意,对session factory来说,这些定义将是全局的(即使定义于类一级),并且类型定义必须先于任何使用.
@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() {
...
}
当使用组合的用户自定义类型时,你必须自己表示列的定义.
@Columns就是为了此目的而引入的.
@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;
...
}
通过在列属性(property)上使用@Index注解,可以在特定列上定义索引,columnNames属性(attribute)将随之被忽略.
@Column(secondaryTable="Cat1")
@Index(name="story1index")
public String getStoryPart1() {
return storyPart1;
}
在嵌入式对象内部,你可以在那些指向该嵌入式对象所属元素的属性上定义该注解.
@Entity
public class Person {
@Embeddable public Address address;
...
}
@Embeddable
public class Address {
@Parent public Person owner;
...
}
person == person.address.owner
某些属性可以在对数据库做插入或更新操作的时候生成.
Hibernate能够处理这样的属性,并触发一个后续的查询来读取这些属性.
@Entity
public class Antenna {
@Id public Integer id;
@Generated(GenerationTime.ALWAYS) @Column(insertable = false, updatable = false)
public String longitude;
@Generated(GenerationTime.INSERT) @Column(insertable = false)
public String latitude;
}
你可以将属性注解为@Generated.
但是你要注意insertability和updatability不要和你选择的生成策略冲突.
如果选择了GenerationTime.INSERT,该属性不能包含insertable列,
如果选择了GenerationTime.ALWAYS,该属性不能包含insertable和updatable列.
@Version属性不可以为
@Generated(INSERT)(设计时), 只能是
NEVER或ALWAYS.
SINGLE_TABLE 是个功能强大的策略,但有时,特别对遗留系统而言,
是无法加入一个额外的辨别符列.
由此,Hibernate引入了辨别符公式(discriminator formula)的概念:
@DiscriminatorFormula是@DiscriminatorColumn的替代品,
它使用SQL片段作为辨别符解决方案的公式( 不需要有一个专门的字段).
@Entity
@DiscriminatorForumla("case when forest_type is null then 0 else forest_type end")
public class Forest { ... }
默认情况下查询顶级实体,Hibernate不会加入带鉴别器列的约束条件子句.
但是如果该列中还包含了和继承层次无关的值(通过@DiscriminatorValue)
就会很不方便.为了解决这个问题,你可以在类上使用@ForceDiscriminator注解
(将该注解放在@DiscriminatorColumn后面).
这样Hibernate在加载实体的时候就可以列出对应的值.
默认情况下,当预期的被关联元素不在数据库中(关乎关联列的错误id),致使Hiberante无法解决关联性问题时,Hibernate就会抛出异常.
这对遗留schema和历经拙劣维护的schema而言,这或有许多不便.
此时,你可用 @NotFound 注解让Hibernate略过这样的元素而不是抛出异常.
该注解可用于 @OneToOne (有外键)、 @ManyToOne 、
@OneToMany 或 @ManyToMany 关联.
@Entity
public class Child {
...
@ManyToOne
@NotFound(action=NotFoundAction.IGNORE)
public Parent getParent() { ... }
...
}
有时候删除某实体的时候需要触发数据库的级联删除.
@Entity
public class Child {
...
@ManyToOne
@OnDelete(action=OnDeleteAction.CASCADE)
public Parent getParent() { ... }
...
}
上面这个例子中,Hibernate将生成一个数据库级的级联删除约束.
Hibernate生成的外键约束的名字可读性相当差,
你可以使用@ForeignKey注解覆盖自动生成的值.
@Entity
public class Child {
...
@ManyToOne
@ForeignKey(name="FK_PARENT")
public Parent getParent() { ... }
...
}
alter table Child add constraint FK_PARENT foreign key (parent_id) references Parent
EJB3为延迟加载和获取模式提供了fetch选项,而Hibernate
这方面提供了更丰富的选项集.为了更好的调整延迟加载和获取策略,Hibernate引入了
一些附加的注解:
@LazyToOne: 定义了@ManyToOne 和 @OneToOne
关联的延迟选项. LazyToOneOption 可以是PROXY (例如:基于代理的延迟加载),NO_PROXY (例如:基于字节码增强的延迟加载 - 注意需要在构建期处理字节码)和 FALSE (非延迟加载的关联)
@LazyCollection: 定义了@ManyToMany和@OneToMany 关联的延迟选项. LazyCollectionOption可以是TRUE (集合具有延迟性,只有在访问的时候才加载), EXTRA (集合具有延迟性,并且所有的操作都会尽量避免加载集合,对于一个巨大的集合特别有用,因为这样的集合中的元素没有必要全部加载)和 FALSE(非延迟加载的关联)
@Fetch:
定义了加载关联关系的获取策略. FetchMode 可以是SELECT (在需要加载关联的时候触发select操作), SUBSELECT(只对集合有效,使用了子查询策略,详情参考Hibernate参考文档) or JOIN (在加载主实体(owner entity)的时候使用SQL JOIN来加载关联关系).
JOIN 将覆写任何延迟属性(通过JOIN策略加载的关联将不再具有延迟性).
The Hibernate annotations overrides the EJB3 fetching options.
Hibernate注解覆写了EJB3提供的获取(fetch)选项.
Annotations
Lazy
Fetch
@[One|Many]ToOne](fetch=FetchType.LAZY)
@LazyToOne(PROXY)
@Fetch(SELECT)
@[One|Many]ToOne](fetch=FetchType.EAGER)
@LazyToOne(FALSE)
@Fetch(JOIN)
@ManyTo[One|Many](fetch=FetchType.LAZY)
@LazyCollection(TRUE)
@Fetch(SELECT)
@ManyTo[One|Many](fetch=FetchType.EAGER)
@LazyCollection(FALSE)
@Fetch(JOIN)
以下是可能的设置方式
用@BatchSizebatch设置集合的batch大小
用@Where或@WhereJoinTable注解设置Where子句,
这两种注解分别应用于目标实体和关联表
用注解@Check来设置check子句
用注解@OrderBy来设置SQL的order by子句
利用@OnDelete(action=OnDeleteAction.CASCADE) 注解设置级连删除策略
你也可以利用@Sort注解定义一个排序比较器(sort comparator),表明希望的比较器类型,无序、自然顺序或自定义排序,三者择一.若你想用你自己实现的comparator,你还需要利用comparator属性(attribute)指明实现类.
注意你需要使用SortedSet或SortedMap接口
@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;
}
关于这些注解更详细的信息,请参阅此前的描述.
Hibernate生成的外键约束的名字可读性相当差,你可以使用@ForeignKey注解覆盖自动生成的值. 注意该注解应该置于关联关系的主体端,inverseName
指向另一端的约束.
@Entity
public class Woman {
...
@ManyToMany(cascade = {CascadeType.ALL})
@ForeignKey(name = "TO_WOMAN_FK", inverseName = "TO_MAN_FK")
public Set<Man> getMens() {
return mens;
}
}
alter table Man_Woman add constraint TO_WOMAN_FK foreign key (woman_id) references Woman
alter table Man_Woman add constraint TO_MAN_FK foreign key (man_id) references Man
比EJB3更胜一筹的是,Hibernate Annotations支持真正的List和Array.
映射集合的方式和以前完全一样,只不过要新增@IndexColumn注解.
该注解允许你指明存放索引值的字段.你还可以定义代表数据库中首个元素的索引值(亦称为索引基数).
常见取值为0或1.
@OneToMany(cascade = CascadeType.ALL)
@IndexColumn(name = "drawer_position", base=1)
public List<Drawer> getDrawers() {
return drawers;
}
假如你忘了设置@IndexColumn,Hibernate会采用bag语义(译注:即允许重复元素的无序集合).
如果你既想使用bag语义,但是又不希望受制于其约束语义,可以考虑使用@CollectionId注解.
Hibernate注解支持true Map映射,如果没有设置@javax.persistence.MapKey,hibernate将key元素或嵌入式对象直接映射到他们所属的列.
要覆写默认的列,可以使用以下注解:
@org.hibernate.annotations.MapKey适用的key为基本类型
(默认为mapkey)或者嵌入式对象,
@org.hibernate.annotations.MapKey适用的key为实体.
双向关联的其中一端在使用@IndexColumn或者 @org.hibernate.annotations.MapKey[ManyToMany]注解需要考虑一些特殊的因素.如果子类存在某个属性映射到索引列,这种情况下是没有问题的,我们可以继续在集合映射的时候使用mappedBy,如下:
@Entity
public class Parent {
@OneToMany(mappedBy="parent")
@org.hibernate.annotations.MapKey(columns=@Column(name="name"))
private Map<String, Child> children;
...
}
@Entity
public class Parent {
...
@Basic
private String name;
@ManyToOne
@JoinColumn(name="parent_id", nullable=false)
private Parent parent;
...
}
但是,如果在子类中没有该属性,我们就不能认为这种关联是真正的双向关联(也就是在关联的一端有信息而另一端没有).因此在这种情况下,我们就不能使用mappedBy将其映射集合.取而代之为下面这种映射方式:
@Entity
public class Parent {
@OneToMany
@org.hibernate.annotations.MapKey(columns=@Column(name="name"))
@JoinColumn(name="parent_id", nullable=false)
private Map<String, Child> children;
...
}
@Entity
public class Parent {
...
@ManyToOne
@JoinColumn(name="parent_id", insertable=false, updatable=false, nullable=false)
private Parent parent;
...
}
注意在上面的映射中,关联的集合端负责更新外键.
另外一个有趣的特征就是可以给bag集合定义一个代理主键.通过这种方式优雅的去除了bag的缺点:update和remove操作更加有效率,每次查询或每个实体可以超过一个EAGER bag.该主键被保存在集合表的一个附加列,该列对于Java应用不可见.@CollectionId注解将一个集合标注为id bag,同时还可以覆写主键列,主键类型以及生成器策略.生成器策略可以是identity,也可以是应用中任何已定义的生成器的名字.
@Entity
@TableGenerator(name="ids_generator", table="IDS")
public class Passport {
...
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="PASSPORT_VISASTAMP")
@CollectionId(
columns = @Column(name="COLLECTION_ID"),
type=@Type(type="long"),
generator = "ids_generator"
)
private Collection<Stamp> visaStamp = new ArrayList();
...
}
Hibernate Annotations还支持核心类型集合(Integer, String, Enums, ......)、
可内嵌对象的集合,甚至基本类型数组.这就是所谓的元素集合.
元素集合可用@CollectionOfElements来注解(作为@OneToMany的替代).
为了定义集合表(译注:即存放集合元素的表,与下面提到的主表对应),要在关联属性上使用@JoinTable注解,joinColumns定义了介乎实体主表与集合表之间的连接字段(inverseJoincolumn是无效的且其值应为空).
对于核心类型的集合或基本类型数组,你可以在关联属性上用@Column来覆盖存放元素值的字段的定义.
你还可以用@AttributeOverride来覆盖存放可内嵌对象的字段的定义.
要访问集合元素,需要将该注解的name属性值设置为"element"("element"用于核心类型,而"element.serial"用于嵌入式对象的serial属性).要访问集合的index/key,则将该注解的name属性值设置为"key".
@Entity
public class Boy {
private Integer id;
private Set<String> nickNames = new HashSet<String>();
private int[] favoriteNumbers;
private Set<Toy> favoriteToys = new HashSet<Toy>();
private Set<Character> characters = new HashSet<Character>();
@Id @GeneratedValue
public Integer getId() {
return id;
}
@CollectionOfElements
public Set<String> getNickNames() {
return nickNames;
}
@CollectionOfElements
@JoinTable(
table=@Table(name="BoyFavoriteNumbers"),
joinColumns = @JoinColumn(name="BoyId")
)
@Column(name="favoriteNumber", nullable=false)
@IndexColumn(name="nbr_index")
public int[] getFavoriteNumbers() {
return favoriteNumbers;
}
@CollectionOfElements
@AttributeOverride( name="element.serial", column=@Column(name="serial_nbr") )
public Set<Toy> getFavoriteToys() {
return favoriteToys;
}
@CollectionOfElements
public Set<Character> getCharacters() {
return characters;
}
...
}
public enum Character {
GENTLE,
NORMAL,
AGGRESSIVE,
ATTENTIVE,
VIOLENT,
CRAFTY
}
@Embeddable
public class Toy {
public String name;
public String serial;
public Boy owner;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
@Parent
public Boy getOwner() {
return owner;
}
public void setOwner(Boy owner) {
this.owner = owner;
}
public boolean equals(Object o) {
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
final Toy toy = (Toy) o;
if ( !name.equals( toy.name ) ) return false;
if ( !serial.equals( toy.serial ) ) return false;
return true;
}
public int hashCode() {
int result;
result = name.hashCode();
result = 29 * result + serial.hashCode();
return result;
}
}
在嵌入式对象的集合中,可以使用 @Parent注解嵌入式对象的某属性.
该属性指向该嵌入式对象所属的集合实体.
旧版的Hibernate Annotations用@OneToMany来标识集合元素.
由于语义矛盾,我们引入了@CollectionOfElements注解.
用@OneToMany来标识集合元素的这种旧有方式目前尚有效,
但是不推荐使用,而且在以后的发布版本中不再支持这种方式.
为了优化数据库访问,你可以激活所谓的Hibernate二级缓存.该缓存是可以按每个实体和集合进行配置的.
@org.hibernate.annotations.Cache定义了缓存策略及给定的二级缓存的范围.
此注解适用于根实体(非子实体),还有集合.
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Forest { ... }
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public SortedSet<Ticket> getTickets() {
return tickets;
}
@Cache(
CacheConcurrencyStrategy usage();
String region() default "";
String include() default "all";
)
usage: 给定缓存的并发策略(NONE,READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)
region (可选的):缓存范围(默认为类的全限定类名或是集合的全限定角色名)
include (可选的):值为all时包括了所有的属性(proterty),为non-lazy时仅含非延迟属性(默认值为all)
Hibernate具有在数据上应用任意过滤器的能力,可在运行期应用于一个给定的session.过滤器需要事先定义好.
@org.hibernate.annotations.FilterDef 或@FilterDefs 定义过滤器声明,为同名过滤器所用.
过滤器声明带有一个name()和一个parameters()数组. 参数提供了在运行时调整过滤器行为的能力,过滤器通过@ParamDef注解定义,该注解包含name和type,你还可以为给定的@FilterDef定义一个defaultCondition()参数,当所有的@Filter中没有任何定义时,可使用该参数定义缺省条件.
@FilterDef (s)可以在类或包一级进行定义.
现在我们来定义应用于实体或集合加载时的SQL过滤器子句.我们使用@Filter,并将其置于实体或集合元素上.
@Entity
@FilterDef(name="minLength", parameters={ @ParamDef( name="minLength", type="integer" ) } )
@Filters( {
@Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),
@Filter(name="minLength", condition=":minLength <= length")
} )
public class Forest { ... }
当这些集合使用关联表来表示关系的时候,你可能需要对于关联表或者目标实体表应用过滤条件.使用@Filter注解可以在目标实体上添加改类约束.
但是如果你打算在关联表上使用,就需要使用@FilterJoinTable注解.
@OneToMany
@JoinTable
//filter on the target entity table
@Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length")
//filter on the association table
@FilterJoinTable(name="security", condition=":userlevel >= requredLevel")
public Set<Forest> getForests() { ... }
由于Hibernate引入了
@org.hibernate.annotations.NamedQuery,
@org.hibernate.annotations.NamedQueries,
@org.hibernate.annotations.NamedNativeQuery 和
@org.hibernate.annotations.NamedNativeQueries 命名式查询,
因此Hibernate在命名式查询上比EBJ3规范中所定义的命名式查询提供了更多的特性.
他们在标准版中添加了可作为替代品的一些属性(attributes):
flushMode: 定义查询的刷新模式(Always, Auto, Commit或Never)
cacheable: 查询该不该被缓存
cacheRegion: 若查询已被缓存时所用缓存的范围
fetchSize: 针对该查询的JDBC statement单次获取记录的数目
timeout: 查询超时
callable: 仅用于本地化查询(native query),对于存储过程设为true
comment: 一旦激活注释功能,我们会在向数据库交送查询请求时看到注释
cacheMode: 缓存交护模式(get, ignore,normal,或refresh)
readOnly: 不管是否从查询获取元素都是在只读模式下
通过@QueryHint注解可以在
@javax.persistence.NamedQuery
中设置hints.另一个重要的优势是可以将这些注解应用到包上
你可以使用SQL片段(亦称为公式),而不是将属性映射到(物理)列. 这种属性是只读的(属性值由公求得).
@Formula("obj_length * obj_height * obj_width")
public long getObjectVolume()
SQL片段可以是任意复杂的,甚至可包含子查询.
@org.hibernate.annotations.Type
覆盖了Hibernate所用的默认类型:这通常不是必须的,因为类型可以由Hibernate正确推得.
关于Hibernate类型的详细信息,请参考Hibernate使用手册.
@org.hibernate.annotations.TypeDef 和@org.hibernate.annotations.TypeDefs允许你来声明类型定义.
这些注解被置于类或包一级.注意,对session factory来说,这些定义将是全局的(即使定义于类一级),并且类型定义必须先于任何使用.
@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() {
...
}
当使用组合的用户自定义类型时,你必须自己表示列的定义.
@Columns就是为了此目的而引入的.
@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;
...
}
通过在列属性(property)上使用@Index注解,可以在特定列上定义索引,columnNames属性(attribute)将随之被忽略.
@Column(secondaryTable="Cat1")
@Index(name="story1index")
public String getStoryPart1() {
return storyPart1;
}
在嵌入式对象内部,你可以在那些指向该嵌入式对象所属元素的属性上定义该注解.
@Entity
public class Person {
@Embeddable public Address address;
...
}
@Embeddable
public class Address {
@Parent public Person owner;
...
}
person == person.address.owner
某些属性可以在对数据库做插入或更新操作的时候生成.
Hibernate能够处理这样的属性,并触发一个后续的查询来读取这些属性.
@Entity
public class Antenna {
@Id public Integer id;
@Generated(GenerationTime.ALWAYS) @Column(insertable = false, updatable = false)
public String longitude;
@Generated(GenerationTime.INSERT) @Column(insertable = false)
public String latitude;
}
你可以将属性注解为@Generated.
但是你要注意insertability和updatability不要和你选择的生成策略冲突.
如果选择了GenerationTime.INSERT,该属性不能包含insertable列,
如果选择了GenerationTime.ALWAYS,该属性不能包含insertable和updatable列.
@Version属性不可以为
@Generated(INSERT)(设计时), 只能是
NEVER或ALWAYS.
SINGLE_TABLE 是个功能强大的策略,但有时,特别对遗留系统而言,
是无法加入一个额外的辨别符列.
由此,Hibernate引入了辨别符公式(discriminator formula)的概念:
@DiscriminatorFormula是@DiscriminatorColumn的替代品,
它使用SQL片段作为辨别符解决方案的公式( 不需要有一个专门的字段).
@Entity
@DiscriminatorForumla("case when forest_type is null then 0 else forest_type end")
public class Forest { ... }
默认情况下查询顶级实体,Hibernate不会加入带鉴别器列的约束条件子句.
但是如果该列中还包含了和继承层次无关的值(通过@DiscriminatorValue)
就会很不方便.为了解决这个问题,你可以在类上使用@ForceDiscriminator注解
(将该注解放在@DiscriminatorColumn后面).
这样Hibernate在加载实体的时候就可以列出对应的值.
默认情况下,当预期的被关联元素不在数据库中(关乎关联列的错误id),致使Hiberante无法解决关联性问题时,Hibernate就会抛出异常.
这对遗留schema和历经拙劣维护的schema而言,这或有许多不便.
此时,你可用 @NotFound 注解让Hibernate略过这样的元素而不是抛出异常.
该注解可用于 @OneToOne (有外键)、 @ManyToOne 、
@OneToMany 或 @ManyToMany 关联.
@Entity
public class Child {
...
@ManyToOne
@NotFound(action=NotFoundAction.IGNORE)
public Parent getParent() { ... }
...
}
有时候删除某实体的时候需要触发数据库的级联删除.
@Entity
public class Child {
...
@ManyToOne
@OnDelete(action=OnDeleteAction.CASCADE)
public Parent getParent() { ... }
...
}
上面这个例子中,Hibernate将生成一个数据库级的级联删除约束.
Hibernate生成的外键约束的名字可读性相当差,
你可以使用@ForeignKey注解覆盖自动生成的值.
@Entity
public class Child {
...
@ManyToOne
@ForeignKey(name="FK_PARENT")
public Parent getParent() { ... }
...
}
alter table Child add constraint FK_PARENT foreign key (parent_id) references Parent
EJB3为延迟加载和获取模式提供了fetch选项,而Hibernate
这方面提供了更丰富的选项集.为了更好的调整延迟加载和获取策略,Hibernate引入了
一些附加的注解:
@LazyToOne: 定义了@ManyToOne 和 @OneToOne
关联的延迟选项. LazyToOneOption 可以是PROXY (例如:基于代理的延迟加载),NO_PROXY (例如:基于字节码增强的延迟加载 - 注意需要在构建期处理字节码)和 FALSE (非延迟加载的关联)
@LazyCollection: 定义了@ManyToMany和@OneToMany 关联的延迟选项. LazyCollectionOption可以是TRUE (集合具有延迟性,只有在访问的时候才加载), EXTRA (集合具有延迟性,并且所有的操作都会尽量避免加载集合,对于一个巨大的集合特别有用,因为这样的集合中的元素没有必要全部加载)和 FALSE(非延迟加载的关联)
@Fetch:
定义了加载关联关系的获取策略. FetchMode 可以是SELECT (在需要加载关联的时候触发select操作), SUBSELECT(只对集合有效,使用了子查询策略,详情参考Hibernate参考文档) or JOIN (在加载主实体(owner entity)的时候使用SQL JOIN来加载关联关系).
JOIN 将覆写任何延迟属性(通过JOIN策略加载的关联将不再具有延迟性).
The Hibernate annotations overrides the EJB3 fetching options.
Hibernate注解覆写了EJB3提供的获取(fetch)选项.
Annotations
Lazy
Fetch
@[One|Many]ToOne](fetch=FetchType.LAZY)
@LazyToOne(PROXY)
@Fetch(SELECT)
@[One|Many]ToOne](fetch=FetchType.EAGER)
@LazyToOne(FALSE)
@Fetch(JOIN)
@ManyTo[One|Many](fetch=FetchType.LAZY)
@LazyCollection(TRUE)
@Fetch(SELECT)
@ManyTo[One|Many](fetch=FetchType.EAGER)
@LazyCollection(FALSE)
@Fetch(JOIN)
以下是可能的设置方式
用@BatchSizebatch设置集合的batch大小
用@Where或@WhereJoinTable注解设置Where子句,
这两种注解分别应用于目标实体和关联表
用注解@Check来设置check子句
用注解@OrderBy来设置SQL的order by子句
利用@OnDelete(action=OnDeleteAction.CASCADE) 注解设置级连删除策略
你也可以利用@Sort注解定义一个排序比较器(sort comparator),表明希望的比较器类型,无序、自然顺序或自定义排序,三者择一.若你想用你自己实现的comparator,你还需要利用comparator属性(attribute)指明实现类.
注意你需要使用SortedSet或SortedMap接口
@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;
}
关于这些注解更详细的信息,请参阅此前的描述.
Hibernate生成的外键约束的名字可读性相当差,你可以使用@ForeignKey注解覆盖自动生成的值. 注意该注解应该置于关联关系的主体端,inverseName
指向另一端的约束.
@Entity
public class Woman {
...
@ManyToMany(cascade = {CascadeType.ALL})
@ForeignKey(name = "TO_WOMAN_FK", inverseName = "TO_MAN_FK")
public Set<Man> getMens() {
return mens;
}
}
alter table Man_Woman add constraint TO_WOMAN_FK foreign key (woman_id) references Woman
alter table Man_Woman add constraint TO_MAN_FK foreign key (man_id) references Man
比EJB3更胜一筹的是,Hibernate Annotations支持真正的List和Array.
映射集合的方式和以前完全一样,只不过要新增@IndexColumn注解.
该注解允许你指明存放索引值的字段.你还可以定义代表数据库中首个元素的索引值(亦称为索引基数).
常见取值为0或1.
@OneToMany(cascade = CascadeType.ALL)
@IndexColumn(name = "drawer_position", base=1)
public List<Drawer> getDrawers() {
return drawers;
}
假如你忘了设置@IndexColumn,Hibernate会采用bag语义(译注:即允许重复元素的无序集合).
如果你既想使用bag语义,但是又不希望受制于其约束语义,可以考虑使用@CollectionId注解.
Hibernate注解支持true Map映射,如果没有设置@javax.persistence.MapKey,hibernate将key元素或嵌入式对象直接映射到他们所属的列.
要覆写默认的列,可以使用以下注解:
@org.hibernate.annotations.MapKey适用的key为基本类型
(默认为mapkey)或者嵌入式对象,
@org.hibernate.annotations.MapKey适用的key为实体.
双向关联的其中一端在使用@IndexColumn或者 @org.hibernate.annotations.MapKey[ManyToMany]注解需要考虑一些特殊的因素.如果子类存在某个属性映射到索引列,这种情况下是没有问题的,我们可以继续在集合映射的时候使用mappedBy,如下:
@Entity
public class Parent {
@OneToMany(mappedBy="parent")
@org.hibernate.annotations.MapKey(columns=@Column(name="name"))
private Map<String, Child> children;
...
}
@Entity
public class Parent {
...
@Basic
private String name;
@ManyToOne
@JoinColumn(name="parent_id", nullable=false)
private Parent parent;
...
}
但是,如果在子类中没有该属性,我们就不能认为这种关联是真正的双向关联(也就是在关联的一端有信息而另一端没有).因此在这种情况下,我们就不能使用mappedBy将其映射集合.取而代之为下面这种映射方式:
@Entity
public class Parent {
@OneToMany
@org.hibernate.annotations.MapKey(columns=@Column(name="name"))
@JoinColumn(name="parent_id", nullable=false)
private Map<String, Child> children;
...
}
@Entity
public class Parent {
...
@ManyToOne
@JoinColumn(name="parent_id", insertable=false, updatable=false, nullable=false)
private Parent parent;
...
}
注意在上面的映射中,关联的集合端负责更新外键.
另外一个有趣的特征就是可以给bag集合定义一个代理主键.通过这种方式优雅的去除了bag的缺点:update和remove操作更加有效率,每次查询或每个实体可以超过一个EAGER bag.该主键被保存在集合表的一个附加列,该列对于Java应用不可见.@CollectionId注解将一个集合标注为id bag,同时还可以覆写主键列,主键类型以及生成器策略.生成器策略可以是identity,也可以是应用中任何已定义的生成器的名字.
@Entity
@TableGenerator(name="ids_generator", table="IDS")
public class Passport {
...
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name="PASSPORT_VISASTAMP")
@CollectionId(
columns = @Column(name="COLLECTION_ID"),
type=@Type(type="long"),
generator = "ids_generator"
)
private Collection<Stamp> visaStamp = new ArrayList();
...
}
Hibernate Annotations还支持核心类型集合(Integer, String, Enums, ......)、
可内嵌对象的集合,甚至基本类型数组.这就是所谓的元素集合.
元素集合可用@CollectionOfElements来注解(作为@OneToMany的替代).
为了定义集合表(译注:即存放集合元素的表,与下面提到的主表对应),要在关联属性上使用@JoinTable注解,joinColumns定义了介乎实体主表与集合表之间的连接字段(inverseJoincolumn是无效的且其值应为空).
对于核心类型的集合或基本类型数组,你可以在关联属性上用@Column来覆盖存放元素值的字段的定义.
你还可以用@AttributeOverride来覆盖存放可内嵌对象的字段的定义.
要访问集合元素,需要将该注解的name属性值设置为"element"("element"用于核心类型,而"element.serial"用于嵌入式对象的serial属性).要访问集合的index/key,则将该注解的name属性值设置为"key".
@Entity
public class Boy {
private Integer id;
private Set<String> nickNames = new HashSet<String>();
private int[] favoriteNumbers;
private Set<Toy> favoriteToys = new HashSet<Toy>();
private Set<Character> characters = new HashSet<Character>();
@Id @GeneratedValue
public Integer getId() {
return id;
}
@CollectionOfElements
public Set<String> getNickNames() {
return nickNames;
}
@CollectionOfElements
@JoinTable(
table=@Table(name="BoyFavoriteNumbers"),
joinColumns = @JoinColumn(name="BoyId")
)
@Column(name="favoriteNumber", nullable=false)
@IndexColumn(name="nbr_index")
public int[] getFavoriteNumbers() {
return favoriteNumbers;
}
@CollectionOfElements
@AttributeOverride( name="element.serial", column=@Column(name="serial_nbr") )
public Set<Toy> getFavoriteToys() {
return favoriteToys;
}
@CollectionOfElements
public Set<Character> getCharacters() {
return characters;
}
...
}
public enum Character {
GENTLE,
NORMAL,
AGGRESSIVE,
ATTENTIVE,
VIOLENT,
CRAFTY
}
@Embeddable
public class Toy {
public String name;
public String serial;
public Boy owner;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSerial() {
return serial;
}
public void setSerial(String serial) {
this.serial = serial;
}
@Parent
public Boy getOwner() {
return owner;
}
public void setOwner(Boy owner) {
this.owner = owner;
}
public boolean equals(Object o) {
if ( this == o ) return true;
if ( o == null || getClass() != o.getClass() ) return false;
final Toy toy = (Toy) o;
if ( !name.equals( toy.name ) ) return false;
if ( !serial.equals( toy.serial ) ) return false;
return true;
}
public int hashCode() {
int result;
result = name.hashCode();
result = 29 * result + serial.hashCode();
return result;
}
}
在嵌入式对象的集合中,可以使用 @Parent注解嵌入式对象的某属性.
该属性指向该嵌入式对象所属的集合实体.
旧版的Hibernate Annotations用@OneToMany来标识集合元素.
由于语义矛盾,我们引入了@CollectionOfElements注解.
用@OneToMany来标识集合元素的这种旧有方式目前尚有效,
但是不推荐使用,而且在以后的发布版本中不再支持这种方式.
为了优化数据库访问,你可以激活所谓的Hibernate二级缓存.该缓存是可以按每个实体和集合进行配置的.
@org.hibernate.annotations.Cache定义了缓存策略及给定的二级缓存的范围.
此注解适用于根实体(非子实体),还有集合.
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Forest { ... }
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public SortedSet<Ticket> getTickets() {
return tickets;
}
@Cache(
CacheConcurrencyStrategy usage();
String region() default "";
String include() default "all";
)
usage: 给定缓存的并发策略(NONE,READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)
region (可选的):缓存范围(默认为类的全限定类名或是集合的全限定角色名)
include (可选的):值为all时包括了所有的属性(proterty),为non-lazy时仅含非延迟属性(默认值为all)
Hibernate具有在数据上应用任意过滤器的能力,可在运行期应用于一个给定的session.过滤器需要事先定义好.
@org.hibernate.annotations.FilterDef 或@FilterDefs 定义过滤器声明,为同名过滤器所用.
过滤器声明带有一个name()和一个parameters()数组. 参数提供了在运行时调整过滤器行为的能力,过滤器通过@ParamDef注解定义,该注解包含name和type,你还可以为给定的@FilterDef定义一个defaultCondition()参数,当所有的@Filter中没有任何定义时,可使用该参数定义缺省条件.
@FilterDef (s)可以在类或包一级进行定义.
现在我们来定义应用于实体或集合加载时的SQL过滤器子句.我们使用@Filter,并将其置于实体或集合元素上.
@Entity
@FilterDef(name="minLength", parameters={ @ParamDef( name="minLength", type="integer" ) } )
@Filters( {
@Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),
@Filter(name="minLength", condition=":minLength <= length")
} )
public class Forest { ... }
当这些集合使用关联表来表示关系的时候,你可能需要对于关联表或者目标实体表应用过滤条件.使用@Filter注解可以在目标实体上添加改类约束.
但是如果你打算在关联表上使用,就需要使用@FilterJoinTable注解.
@OneToMany
@JoinTable
//filter on the target entity table
@Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length")
//filter on the association table
@FilterJoinTable(name="security", condition=":userlevel >= requredLevel")
public Set<Forest> getForests() { ... }
由于Hibernate引入了
@org.hibernate.annotations.NamedQuery,
@org.hibernate.annotations.NamedQueries,
@org.hibernate.annotations.NamedNativeQuery 和
@org.hibernate.annotations.NamedNativeQueries 命名式查询,
因此Hibernate在命名式查询上比EBJ3规范中所定义的命名式查询提供了更多的特性.
他们在标准版中添加了可作为替代品的一些属性(attributes):
flushMode: 定义查询的刷新模式(Always, Auto, Commit或Never)
cacheable: 查询该不该被缓存
cacheRegion: 若查询已被缓存时所用缓存的范围
fetchSize: 针对该查询的JDBC statement单次获取记录的数目
timeout: 查询超时
callable: 仅用于本地化查询(native query),对于存储过程设为true
comment: 一旦激活注释功能,我们会在向数据库交送查询请求时看到注释
cacheMode: 缓存交护模式(get, ignore,normal,或refresh)
readOnly: 不管是否从查询获取元素都是在只读模式下
通过@QueryHint注解可以在
@javax.persistence.NamedQuery
中设置hints.另一个重要的优势是可以将这些注解应用到包上
发表评论
-
ConcurrentHashMap与CopyOnWriteArrayList比较。
2010-12-14 10:24 1708ConcurrentHashMap ConcurrentH ... -
Servlet与Struts action线程安全问题分析
2010-03-24 19:45 1283Servlet/JSP技术和ASP、PHP等相比,由于其多线程 ... -
JVM调优
2010-03-24 19:37 1143原文: http://blog.csdn.net/tyrone ... -
HttpURLConnection VS HttpClient性能测试
2010-03-16 14:19 9001版本: HttpURLConnection jdk1.6;H ... -
jdk 1.6新特性
2010-02-03 09:27 36762006 年底,Sun 公司发布了 Java Standard ... -
REST是什么
2009-11-06 18:27 1208REST架构风格是全新的针对Web应用的开发风格,是当今世界最 ... -
jira企业版linux下安装和破解
2009-08-07 13:42 57221、下载地址:http://www.atlassian.com ... -
log4j输出到文件和数据库
2009-05-20 21:07 4630官方API地址:http://logging.apache.o ... -
Log4j详细配置
2009-05-19 10:51 928一、前言: log4j 是一个开放源码项目,是广泛 ... -
ANT-build.xml文件详解
2009-03-12 13:54 1557Ant的概念 可能有些读者并不连接什么是Ant以及 ... -
tomcat配置说明和内存扩容
2009-03-05 14:37 24831. 如何加大tomcat连接数 在tomcat配置文件ser ... -
ehCache在acegi中的应用
2009-03-03 16:56 2897EhCache一般用途如下:Hibernate缓存,DA ... -
特殊字符转义
2009-02-24 10:52 1012请看附件图片。 -
Eclipse快捷键大全
2009-02-16 15:06 878Eclipse中自定义设置快捷键: Window --> ... -
Mime类型收集
2009-02-12 15:41 1023网方网站:http://www.mimetype.org/ ... -
lukeall-0.8.1.jar Lucene索引查看工具
2008-12-30 12:54 7167lukeall-0.8.1.jar 在windows下双击, ... -
EJB3.0-JPA实体的注解规范以及Hibernate特有的扩展(上)
2008-12-29 15:45 4090本章内容覆盖了EJB ... -
常见异常解析
2008-12-29 11:36 11621. java.lang.nullpointerexce ... -
org.apache.commons.lang.builder
2008-12-26 10:10 2342在org.apache.commons.lang.b ... -
java(Web)中相对路径,绝对路径问题
2008-11-28 11:51 18331.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或 ...
相关推荐
### EJB3.0-JPA实体的注解规范以及Hibernate特有的扩展 #### 一、概述 EJB3.0引入了一种新的编程模型,它基于Java Persistence API (JPA),使得开发人员能够更加轻松地创建企业级应用。JPA允许使用POJO(Plain Old...
EJB3.0实体的注解规范主要涵盖了Java企业版(Java EE)中实体Bean的定义方式,这一规范也适用于Java Persistence API (JPA),并且整合了Hibernate的特有扩展。在EJB3.0中,实体Bean被设计为简单的Plain Old Java ...
综上所述,ejb3.0规范PDF包含了大量的信息,从配置简化到实体Bean的JPA集成,再到会话Bean、消息驱动Bean的使用,以及依赖注入、接口驱动编程、事务管理和安全性等多个方面,为Java EE开发者提供了全面的指导。...
【EJB学习大全】是针对企业级Java应用开发的一个重要主题,主要涵盖了EJB3.0、JPA教程以及实战EJB的相关知识。EJB,全称为Enterprise JavaBeans,是Java平台上的一个核心组件,主要用于构建分布式、面向服务的企业级...
在"ejb3.0入门经典教程-source"这个压缩包中,包含了书中各个章节的示例代码,覆盖了EJB 3.0的各个方面,例如实体Bean的创建、会话Bean的使用、事务管理、安全性设置以及JPA的持久化操作等。这些源码对于初学者来说...
在EJB 3.0中,开发者可以使用注解(Annotations)来声明实体、会话和消息驱动bean,以及它们的相关行为。例如,`@Entity`用于标记实体bean,`@Stateless`和`@Stateful`分别表示无状态和有状态会话bean,`@Message...
### JPA学习笔记-EJB-02JPA属性注解 #### 一、引言 在上一篇文章中,我们简要介绍了Java Persistence API (JPA)的基础知识,包括它的基本部署和操作流程,从而让我们对JPA有了初步的认识。本文将继续深入探讨JPA的...
- **实体Bean(Entity Beans)**:EJB 3.0中的实体Bean不再需要编写复杂的EJB接口和实现类,而是通过JPA(Java Persistence API)进行持久化管理,可以利用注解(Annotations)直接在实体类上声明数据存储的相关属性...
EJB 3.0引入了Java Persistence API(JPA),使得实体bean的管理更加简单,可以与ORM(对象关系映射)框架如Hibernate集成。 **3. EJB 3.0新特性** - **注解驱动**:例如,`@Entity`用于标记实体bean,`@EJB`用于...
3. **容器管理的依赖注入(Dependency Injection)**:EJB 3.0引入了JSR 250规范,允许通过@EJB、@Resource、@PersistenceContext和@PersistenceUnit等注解实现依赖注入,简化了组件间的协作。 4. **查询语言(JPQL...
1. 注解驱动:EJB 3.0允许开发者通过注解来声明组件的元数据,如实体Bean的@Entity,会话Bean的@Stateless或@Stateful,以及服务接口的@Service等。这种方式避免了EJB 2.x中的XML配置文件,使得代码更加简洁明了。 ...
同时,EJB 3.0支持JPA(Java Persistence API),允许开发者使用Hibernate、TopLink等持久化框架。 2. **会话Bean(Session Beans)**:会话Bean用于处理业务逻辑。EJB 3.0允许开发者使用无状态会话Bean(`@...
这些jar可能包含了实体bean的实现库,如`hibernate-entitymanager.jar`(如果使用Hibernate作为JPA实现)。 3. **Session Beans**:会话bean(Session Bean)是EJB3.0中的业务逻辑组件,它们负责处理应用逻辑。相关...
3. **实体 Bean**:EJB3.0中的实体Bean(Entity Bean)基于JPA,不再需要Entity Home和Entity Bean接口,而是使用简单的Java POJO(Plain Old Java Object)作为数据模型,并通过`@Id`注解定义主键。 4. **会话 ...
总结来说,`ejb3-persistence.jar`和`hibernate-annotations.jar`是Java企业级开发中的重要组件,它们为开发者提供了简单易用的持久化框架,使得在面向对象的编程环境下可以轻松地管理和操作数据库,提升了开发效率...
EJB 3.0的持久化API实际上是基于JPA规范的实现。Entity Beans的概念被重新定义,不再需要EJB容器管理的事务和生命周期,而是更接近于POJO(Plain Old Java Object)。JPA提供了一个标准接口来操作持久化对象,兼容...
2. 持久化:通过`@Entity`注解,EJB3.0提供了更直观的持久化模型,支持JPA(Java Persistence API),并与Hibernate等ORM框架集成。 3. 自动事务管理:EJB容器自动处理事务,开发者无需关心底层的事务控制。 4. 无...
4. **持久化框架(Persistence Framework)**:EJB3.0集成了JPA(Java Persistence API),使得开发者可以使用ORM(Object-Relational Mapping)工具,如Hibernate,进行数据持久化。`@PersistenceContext`用于注入...