`

HIbernate注解

阅读更多

 

Hibernate注解

文章分类:Web前端 

@org.hibernate.annotations.Entity(dynamicUpdate=true,dynamicInsert=true)

 

 

 

类定义前添加;

 

作用:当只需更新某个表的部分字段时,其他字段不会更新。在性能优化方面有一定的帮助。

 

 

 

 基本属性映射

通过 @Basic 可以声明属性的存取策略:

@Basic(fetch=FetchType.EAGER)   即时获取(默认的存取策略)

@Basic(fetch=FetchType.LAZY)    延迟获取

 

通过 @Temporal 定义映射到数据库的时间精度:

@Temporal(TemporalType=DATE)       日期

@Temporal(TemporalType=TIME)       时间

@Temporal(TemporalType=TIMESTAMP) 两者兼具

 

使用 @Lob 映射Blob或Clob类型:根据属性类型决定

java.sql.CLOB, Character[], char[], String 将映射为 Clob

java.sql.BLOB, Byte[], byte[], serializable 将映射为 Blob

 

 

 

 

利用Hibernate Annotations进行对象关联映射(一)

1.     简介

在使用Hibernate的时候,对于对象之间的关联,往往是比较复杂的,比如如何映射多对多关系,如何映射双向/单向的关系等等。

 

在JDK5.0出来之前,往往很头疼于映射一个Collection类型的属性,好像有n多的参数需要设置,inverse、mappedby等等又是什么意思呢?如何确定关联双方的维护关系?

 

当JDK5.0横空出世之后,它带来的Generic、Annotation等等新的特性,给Hibernate带来了巨大的活力。随着新版本Hibernate的发布,我们可以发现,使用Hibernate,使用JDK的新特性,给我们的开发工作带来了很大的便利。

 

现在,我可以自由地创建领域模型类图,而很少关心它的存储,因为,我只需要用很少的几个Annotation,一切似乎都在完美地运转,使用它的缺省设置,无需过多的定义,就能满足我的项目中绝大部分的要求。

 

是不是很吸引人?下面,我尝试将一对一、一对多、多对多、双向、单向等概念,一次性集中对照着讨论一下,然后以一些例子来进行具体的说明,希望那些和我一样,对hibernate有兴趣的、曾经头疼于它的那些Collection等映射方法的朋友们有些帮助。

 

下面这一章的内容有点晦涩,如果你看不下去了,可以看看后面举例的那一章,映射设置与SQL语句对照着看,可能更加容易理解。(女性朋友们不要骂我,我不是SuperMan J )

 

2.     关联类型及映射方法

2.1  一对一

两个实体之间是一对一的关系。我们可以想象一下,一对一关系,表明两个实体之间关系非常密切。两个实体,在数据库中会映射成两张表。所以这两张表之间必定需要建立关联。有两种方法可以实现一对一的关系映射。

 

 

 

 

 

1、  两张表使用同样的主键值:

 

@Entitypublic class Body {               @Id               public Long getId() { return id; }               @OneToOne(cascade = CascadeType.ALL, usePKasFK=true)               public Heart getHeart() {                              return heart;               }               ...}@Entitypublic class Heart {    @Id(generate = GeneratorType.NONE)    public Long getId() { ...}}以上例子表明两张表将使用同样的键值。但是这种方法在hibernate3beta2版本中仍然是有局限的。

 

 

 

2、  通过外键关联

 

也就是在拥有者一边,指定它的外键

 

@Entitypublic class Customer implements Serializable {    @OneToOne(cascade = CascadeType.ALL)    @JoinColumn(name="passport_fk")    public Passport getPassport() {        ...    }@Entitypublic class Passport implements Serializable {    @OneToOne(mappedBy = "passport")    public Customer getOwner() {    ...}      上边的例子就是一个使用外键的实例。使用JoinColumn声明来指定数据库中的外键。上边的例子同时也表明,这是一个双向的一对一关系。在这种双向的关系中,你必须让拥有者这一边,负责被拥有者的创建、删除、更新操作(cascade = CascadeType.ALL)。同时,你必须在被拥有者那边定义,说它的信息不需要自己维护,这是通过定义mappedBy属性来决定的。这个属性的值,就是它的拥有者对被拥有者关联的属性的值。如上边的例子,mappedBy的意思就是说:我的(Passport的)信息是由对方的(Customer的)passport属性来映射的。

 

2.1.1           更多的解释

1、  如果没有标识cascade属性的值,表明它们之间没有任何关联操作。你必须先将属性的值保存之后,才能将主体的值保存。

 

2、  双向一对一关联中,可以在任何一方设置mappedBy属性,也可以在任何一方都不设置mappedBy。如果没有任何一方设置mappedBy,就意味着在双方的数据库表中都会保留着对对方的关联外键(双向关联)。在双向一对一关联中,完全没有必要在双方的数据库表中都保留对对方的关联外键,形成数据库主键双向关联。所以最好能设置一下mappedBy属性。虽然数据库中没有双方关联,但是在实体层,你仍然可以从任意一方访问到另外一方。

 

3、  如果有一方设置了mappedBy属性,则在设置mappedBy一方,不会有对方的外键关联。

 

 

 

 

 

2.2  多对一

多对一的关系比较简单,一个实体到另外一个实体的应用,在数据库中就表现为多对一的关系。

 

@Entity()public class Flight implements Serializable {    @ManyToOne( cascade = {CascadeType.CREATE, CascadeType.MERGE} )    @JoinColumn(name="COMP_ID")    public Company getCompany() {        return company;    }    ...}上述例子表明,这是一种多对一关系,外键是COMP_ID。这个外键的定义也是可选的,在生成数据库的时候,如果你没有定义这个外键的名称,那么默认的规则就是“属性名_属性对应的ID”,如上例,假设Company的主键名为ID,那么,如果你不指定JoinColumn,默认生成的外键名就是“company_id”,因为company是属性的名称,而id是Company的主键名称。

 

2.2.1           更多的解释

多对一,如果是双向的,就意味着另外一端是一对多,这种一对多的关系,在数据库里面建立外键的时候,必定是在多的那一端,创建一个外键,关联到一那一端。所以ManyToOne是没有mappedBy属性的。只有在双向一对多关联中,才能在多的那端定义mappedBy属性。

 

2.3  一对多

通常,一对多的关系,在实体里面的表现就是一个集合对象。由于JDK5可以使用范型,所以,除非你使用了范型,否则,必须在一对多的关系中指定目标实体的名称。

 

 

 

2.3.1           双向一对多

@Entitypublic class Troop {    @OneToMany(mappedBy="troop")    public Set<Soldier> getSoldiers() {    ...}@Entitypublic class Soldier {    @ManyToOne    @JoinColumn(name="troop_fk")    public Troop getTroop() {    ...}上面就是一个双向的例子。在mappedBy这一端,你不能定义任何物理参数(即有关数据库主键、外键之类的定义)。其实,所谓mappedBy,意思就是在mappedBy这一端,数据库里面没有任何外键关联到对方的表。这种关联是在对方的表中建立的。

 

 

 

2.3.2           单向一对多

所谓单向一对多,也就是说在“一”这一端,能访问所有的“多”,但是在“多”这一端却不能访问“一”的信息。

 

 

 

实现这种单向一对多,也有两种方法,下面这种方法是不建议的:

 

 

 

@Entitypublic class Customer implements Serializable {    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)    @JoinColumn(name="CUST_ID")    public Set<Ticket> getTickets() {    ...}@Entitypublic class Ticket implements Serializable {    ... //no bidir}这种方法就是在对方的表中添加一个外键关联。

 

 

 

2.3.3           使用表关联建立单向一对多关系

 

 

在单向一对多关联中,下面的方法才是推荐使用的方法。

 

你可以在“一”和“多”之间建立一张关联表。

 

@Entity()public class Trainer {    @OneToMany    @AssociationTable(                       table=@Table(name="TrainedMonkeys"),            joinColumns = { @JoinColumn( name="trainer_id") },            inverseJoinColumns = @JoinColumn( name="monkey_id")    )    public Set<Monkey> getTrainedMonkeys() {    ...}@Entitypublic class Monkey {    ... //no bidir}你可以看到,在“一”这一端,你需要定义关联表的信息:关联表的名称,关联表的外键(指向“一”的外键),关联表的反向外键(指向“多”的外键)。

 

 

 

2.3.4           缺省的一对多映射

如果你指定一个集合对象为一对多关联,但是却没有任何物理数据库表方面的描述,那么默认的情况就是使用关联表的方式,也就是说Hibernate将会给你自己建立关联表。而且关联表的名称是“一”端表名称+下划线+“多”端的表名;关联表对“一”表的外键是“一”表的名称+下划线+“一”表的主键名称;关联表对“多”端的外键就是“一”表的属性名称+下划线+“多”端的主键名称。举个例子:

 

 

 

@Entity()public class Trainer {    @OneToMany    public Set<Tiger> getTrainedTigers() {    ...}@Entitypublic class Tiger {    ... //no bidir}上述例子中,建立的关联表名称为“Trainer_Tiger”,到Trainer的外键是“trainer_id”,到Tiger的外键是“trainedTigers_id”。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics