hibernate注解
现在EJB3实体bean是纯粹的POJO,实际上表达了和Hibernate持久化实体对象同样的概念。hibernate注解既可以注解到get方法上,也可以注解到属性上。一个实体类要么都注解到类的属性上,要么都注解到get方法上。
@Entity
@Table(name="tbl_Fligh")
public class Flight implements Serializable {
Long id;
@Id
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
}
@Entity(name="tableName")
该注解将一个类声明为实体Bean。name为可选,对应数据库中的一个表。
@Table(name="",catalog="",schema="")
@Table是类的一级注释,通过它可用为实体指定表(Table),目录(Catalog),和schema的名字,如果没有@Table,那么系统自动使用默认值:实体的短类名(不带包名)
@id
定义映射到数据库表的主键的属性,一个实体只能有一个属性被映射为主键。
@GeneratedValue(strategy=GenerationType,generator = "")
strategy表示主键生成策略,有AUTO,INDENTITY,SEQUENCE,和TABLE4种,默认为AUTO。
generator表示主键生成器的名称,这个属性通常和ORM框架相关。
@Basic
@Basic表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的getXxx()方法,默认即为@Basic。
fetch,表示该属性的读取策略,有EAGER和LAZY两种,表示立即抓取和延迟加载,默认为EAGER。
optional,表示该属性是否允许为null,默认为true。
@Transient
表示该属性并非一个到数据表的字段的映射,ORM框架将忽略该属性。如果一个属性并非数据库表的字段映射,就务必将其标识为@Transient,否则ORM框架默认将其注解为@Basic。
@UniqueConstraints 可以定义表的唯一约束。
@Table(name="tbl_sky",
uniqueConstraints = {@UniqueConstraint(columnNames={"month", "day"})}
)
上述代码在"month"和"day"两个字段上加上unique constrainst.
@Version 注解用于支持乐观锁版本控制。
根据EJB3规范,Version列可以使用numeric类型(推荐方式)也可以使用timestamp类型。Hibernate支持任何自定义类型,只要该类型实现了UserVersionType.
@Entity
public class Flight implements Serializable {
...
@Version
@Column(name="OPTLOCK")
public Integer getVersion() { ... }
}
version属性映射到 "OPTLOCK" 列,entity manager 使用这个字段来检测冲突。 一般可以用 数字 或者 timestamp 类型来支持 version.
@Temporal
默认情况下,实体中使用的数据类型是java.sql包下的类,但此时如果要使用java.util包中的时间日期类型,则需要而外标注@Temporal注释来说明转化成java.util包中的类型。
@Temporal(value=TemporalType.DATE) 等于java.sql.Date
TemporalType.TIME 时间型,精确到时分秒,例如“20:00:00”
TemporalType.Date 日期型,精确到年月日,例如“2008-08-08”
TemporalType.TIMESTAMP 包括日期和时间
例如:
@Temporal(TemporalType.TIME)
java.util.Date getDepartureTime() { ... } // persistent property
@Lob 注解属性将被持久化为 Blog 或 Clob 类型。具体的java.sql.Clob, Character[], char[] 和 java.lang.String 将被持久化为 Clob 类型. java.sql.Blob, Byte[], byte[] 和 serializable type 将被持久化为 Blob 类型。
@Lob
public String getFullText() {
return fullText; // clob type
}
@Lob
public byte[] getFullCode() {
return fullCode; // blog type
}
@Column
描述了数据表中该字段的详细定义。这对于根据JPA注解生成数据表结构的工具非常有作用。
name,表示数据库表该字段的名称, 默认与属性名称一致。
nullable,表示该字段是否允许为null,默认为true。
unique,表示该字段是否是唯一标识,默认为false。
length,表示该字段的大小,仅对String类型的字段有效。
insertable,表示在ORM框架执行插入操作时,该字段是否应出现在INSERT语句中,默认为true。
updateable表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true。
columnDefinition,表示该字段在数据中的实际类型,通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段究竟是DATE,TIME还是TIMESTAMP。String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库BLOB或TEXT字段类型,该属性非常有用。例如:
@Cloumn(name="BIRTH",nullable="false",columnDefinition="DATE")
public String getBirhday(){
return birthday;
}
如:
@Column(columnDefinition="int default 0",nullable=false,insertable=false,updatable=false)
@Column(columnDefinition="varchar(255) default ‘x‘",nullable=false,insertable=false,updatable=false)
@Column(columnDefinition="TIMESTAMPTZ default ‘2009-01-01 00:00:00‘",nullable=false,insertable=false,updatable=false)
@Entity
public class Flight implements Serializable {
...
@Column(updatable = false, name = "flight_name", nullable = false, length=50)
public String getName() { ... }
}
定义 name 属性映射到 flight_name column, not null, can‘t update, length equal 50
@Column(
name="columnName"; (1) 列名
boolean unique() default false; (2) 是否在该列上设置唯一约束
boolean nullable() default true; (3) 列可空?
boolean insertable() default true; (4) 该列是否作为生成 insert语句的一个列
boolean updatable() default true; (5) 该列是否作为生成 update语句的一个列
String columnDefinition() default ""; (6) 默认值
String table() default ""; (7) 定义对应的表(deault 是主表)
int length() default 255; (8) 列长度
int precision() default 0; // decimal precision (9) decimal精度
int scale() default 0; // decimal scale (10) decimal长度
}
precision表示数字中的有效位。如果没有指定precision的话,Oracle将使用38作为精度。
scale表示数字小数点右边的位数,scale默认设置为0
columnDefinition相当于下面创建表语句bbsTitle nchar(60) NOT NULL DEFAULT (‘0.00‘)的bbsTitle nchar(60) NOT NULL DEFAULT (‘0.00‘)部分。
create table bbs_T (
bbsTitle nchar(60) NOT NULL DEFAULT (‘0.00‘),
bbsContent nchar(200),
iniID int identity,
fatieTime nchar(20)
);
//columnDefinition添加大于等于0的约束
@Column(name = "AVAILABLE_QTY",nullable = false,columnDefinition = "int check(available_qty >=0)")
public Integer getAvailableQty(){
return availableQty;
}
@Embeddable与@Embedded
嵌入式对象(又称组件)将资格字段组合成一个类,并作为这个Entity的一个属性。
组件类必须在类一级定义 @Embeddable 注解。在特定的实体关联属性上使用 @Embeddable 和 @AttributeOverride 注解可以覆盖该属性对应的嵌入式对象的列映射。被@Embeddable注解的类是不会生成对应的表,也不是实体类,它的属性会被嵌入到其他实体类中,作为其他实体类的属性。
例如:Person 类定义了 Address 和 Country 对象
@Entity
public class Person implements Serializable {
// Persistent component using defaults
Address homeAddress;
@Embedded
@AttributeOverrides( {
@AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),
@AttributeOverride(name="name", column = @Column(name="bornCountryName") )
} )
Country bornIn;
...
}
生成的Person表将有city,iso2,countryName,bornIso2,bornCountryNamexhx几个列。Address和Country不是实体类不会生成表。
@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; }
...
}
映射继承关系
参考EJB3的继承映射
映射实体Bean的关联关系
参考EJB3的关联关系
映射二级列表
使用类一级的 @SecondaryTable 和 @SecondaryTables 注解可以实现单个实体到多个表的映射。使用 @Column 或者 @JoinColumn 注解中的 table 参数可以指定某个列所属的特定表。
@Entity
@Table(name="MainCat")
@SecondaryTables({
@SecondaryTable(name="Cat1", pkJoinColumns={
@PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id")}),
@SecondaryTable(name="Cat2", uniqueConstraints={
@UniqueConstraint(columnNames={"storyPart2"})})
})
public class Cat implements Serializable {
private Integer id;
private String name;
private String storyPart1;
private String storyPart2;
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public String getName() {
return name;
}
@Column(table="Cat1")
public String getStoryPart1() {
return storyPart1;
}
@Column(table="Cat2")
public String getStoryPart2() {
return storyPart2;
}
上述例子中, name 保存在 MainCat 表中,storyPart1保存在 Cat1 表中,storyPart2 保存在 Cat2 表中。 Cat1 表通过外键 cat_id 和 MainCat 表关联, Cat2 表通过 id 列和 MainCat 表关联。对storyPart2 列还定义了唯一约束。
*******************
hibernate的CascadeType属性
JPA中的CascadeType.ALL并不等于{CascadeType.PESIST,CascadeType.REMOVE,CascadeType.MERGE,CascadeType.REFRESH}
在Hibernate中调用session.save() or session.update()并不能触发 {CascadeType.PESIST,CascadeType.REMOVE,CascadeType.MERGE,CascadeType.REFRESH} 的级联操作,而能触发CascadeType.ALL的级联。如不希望用CascadeType.ALL,需要使用Hibernate自身对 cascade的注解 @Cascade(value=org.hibernate.annotations.CascadeType.SAVE_UPDATE)
cascade属性的可能值有
all: 所有情况下均进行关联操作,即save-update和delete。
none: 所有情况下均不进行关联操作。这是默认值。
save-update: 在执行save/update/saveOrUpdate时进行关联操作。
delete: 在执行delete 时进行关联操作。CascadeType.DELETE:当调用session.delete(A)的时候,级联删除关联的对象。(注:先调用A.setB(null),再调用session.delete(A),这样是级联删不掉B的。
delete-orphan只应用在OneToMany中,能级联删除Many集合中的子元素。CascadeType.DELETE_ORPHAN:
JPA并不支持delete-orphan,但并不明白hibernate reference中为什么可以在OneToMany中添加属性orphanRemoval=true的属性。事实上,要用hibernate独有的注解 @Cascade([email protected]_ORPHAN)来达到此目的。
all-delete-orphan:(一对多级联删除) 当一个节点在对象图中成为孤儿节点时,删除该节点。
all-delete-orphan 的能力:
1. 当保存或更新父方对象时,级联保存或更新所有关联的子方对象,相当于 cascade 为 save-update
2. 当删除父方对象时,级联删除所有关联的子方对象,相当于 cascade 为 delete
3. 删除不再和父方对象关联的所有子方对象
@Cascade({CascadeType.SAVE_UPDATE,CascadeType.DELETE_ORPHAN})
*******************
对于lazy加载,虽然不能获取被延迟对象的其它的属性但是仍然能够获取的被延迟对象的主键ID属性。
例如:${organ.user.id},user是被延迟加载的对象,仍然可以获取它的id。
在级联保存中,如果主表保存失败,则从表就得不到主表的ID而保存时报出主表ID 不能为null。
****************
@Formula注解
@Formula("(select COUNT(*) from user)")
private int count;
注意:
<property name="belongOrganN" type="string" insert="false" update="false" formula="(select x.OrganShortN from tsy_organ x where x.OrganID= BelongOrganID)"/> 或
<property name="belongOrganN" type="string" insert="false" update="false">
<formula><![CDATA[(select x.OrganShortN from tsy_organ x where x.OrganID= BelongOrganID)]]></formula>
</property>
formula="( ... )",里面的是sql语句,字段和表名都应该和数据库相对应,若带有参数如(select x.OrganShortN from tsy_organ x where x.OrganID= BelongOrganID),OrganID是tsy_organID表中的字段,BelongOrganID名称表示当前<property>元素所在的映射文件或实体model类对应表的字段名。
注解必须是在属性上的,如果有任何一个注解在方法上,那么@Formula将失效
如果配置文件formula="( sql )",这个括号不能少,不然会报错,我试了几次,没括号就报错,添上就没问题;如果是注解sql语句外一样需要被括号包含起来,否则会报错。
@Formula("(select x.OrganShortN from tsy_organ x where x.OrganID= BelongOrganID)")
private String name;