hibernate 注解 收藏
一般情况下,注解@cascade用在@oneToMany的情况下,在@manyToOne的情况下不需要设置,即默认值Null,比如我们在删除部门的时候通常会删除该部门的员工信息,所以在部门表中Dept的employees上面加注解:@oneToMany(cascade=cascadeType.all)
转:http://www.24xuexi.com/w/2011-06-07/91373.html
1、@Entity(name="EntityName")
必须,name为可选,对应数据库中一的个表
2、@Table(name="",catalog="",schema="")
可选,通常和@Entity配合使用,只能标注在实体的class定义处,表示实体对应的数据库表的信息
name:可选,表示表的名称.默认地,表名和实体名称一致,只有在不一致的情况下才需要指定表名
catalog:可选,表示Catalog名称,默认为Catalog("").
schema:可选,表示Schema名称,默认为Schema("").
3、@id
必须
@id定义了映射到数据库表的主键的属性,一个实体只能有一个属性被映射为主键.置于getXxxx()前.
4、@GeneratedValue(strategy=GenerationType,generator="")
可选
strategy:表示主键生成策略,有AUTO,INDENTITY,SEQUENCE和TABLE4种,分别表示让ORM框架自动选择,
根据数据库的Identity字段生成,根据数据库表的Sequence字段生成,以有根据一个额外的表生成主键,默认为AUTO
generator:表示主键生成器的名称,这个属性通常和ORM框架相关,例如,Hibernate可以指定uuid等主键生成方式.
示例:
@Id
@GeneratedValues(strategy=StrategyType.SEQUENCE)
publicintgetPk(){
returnpk;
}
5、@Basic(fetch=FetchType,optional=true)
可选
@Basic表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的getXxxx()方法,默认即为@Basic
fetch:表示该属性的读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER.
optional:表示该属性是否允许为null,默认为true
示例:
@Basic(optional=false)
publicStringgetAddress(){
returnaddress;
}
6、@Column
可选
@Column描述了数据库表中该字段的详细定义,这对于根据JPA注解生成数据库表结构的工具非常有作用.
name:表示数据库表中该字段的名称,默认情形属性名称一致
nullable:表示该字段是否允许为null,默认为true
unique:表示该字段是否是唯一标识,默认为false
length:表示该字段的大小,仅对String类型的字段有效
insertable:表示在ORM框架执行插入操作时,该字段是否应出现INSETRT语句中,默认为true
updateable:表示在ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true.对于一经创建就不可以更改的字段,该属性非常有用,如对于birthday字段.
columnDefinition:表示该字段在数据库中的实际类型.通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP.此外,String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的BLOB或TEXT字段类型,该属性非常有用.
示例:
@Column(name="BIRTH",nullable="false",columnDefinition="DATE")
publicStringgetBithday(){
returnbirthday;
}
7、@Transient
可选
@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.
如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则,ORM框架默认其注解为@Basic
示例:
//根据birth计算出age属性
@Transient
publicintgetAge(){
returngetYear(newDate())-getYear(birth);
}
8、@ManyToOne(fetch=FetchType,cascade=CascadeType)
可选
@ManyToOne表示一个多对一的映射,该注解标注的属性通常是数据库表的外键
optional:是否允许该字段为null,该属性应该根据数据库表的外键约束来确定,默认为true
fetch:表示抓取策略,默认为FetchType.EAGER
cascade:表示默认的级联操作策略,可以指定为ALL,PERSIST,MERGE,REFRESH和REMOVE中的若干组合,默认为无级联操作
targetEntity:表示该属性关联的实体类型.该属性通常不必指定,ORM框架根据属性类型自动判断targetEntity.
示例:
//订单Order和用户User是一个ManyToOne的关系
//在Order类中定义
@ManyToOne()
@JoinColumn(name="USER")
publicUsergetUser(){
returnuser;
}
9、@JoinColumn
可选
@JoinColumn和@Column类似,介量描述的不是一个简单字段,而一一个关联字段,例如.描述一个@ManyToOne的字段.
name:该字段的名称.由于@JoinColumn描述的是一个关联字段,如ManyToOne,则默认的名称由其关联的实体决定.
例如,实体Order有一个user属性来关联实体User,则Order的user属性为一个外键,
其默认的名称为实体User的名称+下划线+实体User的主键名称
示例:
见@ManyToOne
10、@OneToMany(fetch=FetchType,cascade=CascadeType)
可选
@OneToMany描述一个一对多的关联,该属性应该为集体类型,在数据库中并没有实际字段.
fetch:表示抓取策略,默认为FetchType.LAZY,因为关联的多个对象通常不必从数据库预先读取到内存
cascade:表示级联操作策略,对于OneToMany类型的关联非常重要,通常该实体更新或删除时,其关联的实体也应当被更新或删除
例如:实体User和Order是OneToMany的关系,则实体User被删除时,其关联的实体Order也应该被全部删除
示例:
@OneTyMany(cascade=ALL)
publicListgetOrders(){
returnorders;
}
11、@OneToOne(fetch=FetchType,cascade=CascadeType)
可选
@OneToOne描述一个一对一的关联
fetch:表示抓取策略,默认为FetchType.LAZY
cascade:表示级联操作策略
示例:
@OneToOne(fetch=FetchType.LAZY)
publicBloggetBlog(){
returnblog;
}
12、@ManyToMany
可选
@ManyToMany描述一个多对多的关联.多对多关联上是两个一对多关联,但是在ManyToMany描述中,中间表是由ORM框架自动处理
targetEntity:表示多对多关联的另一个实体类的全名,例如:package.Book.class
mappedBy:表示多对多关联的另一个实体类的对应集合属性名称
示例:
User实体表示用户,Book实体表示书籍,为了描述用户收藏的书籍,可以在User和Book之间建立ManyToMany关联
@Entity
publicclassUser{
privateListbooks;
@ManyToMany(targetEntity=package.Book.class)
publicListgetBooks(){
returnbooks;
}
publicvoidsetBooks(Listbooks){
this.books=books;
}
}
@Entity
publicclassBook{
privateListusers;
@ManyToMany(targetEntity=package.Users.class,mappedBy="books")
publicListgetUsers(){
returnusers;
}
publicvoidsetUsers(Listusers){
this.users=users;
}
}
两个实体间相互关联的属性必须标记为@ManyToMany,并相互指定targetEntity属性,
需要注意的是,有且只有一个实体的@ManyToMany注解需要指定mappedBy属性,指向targetEntity的集合属性名称
利用ORM工具自动生成的表除了User和Book表外,还自动生成了一个User_Book表,用于实现多对多关联
13、@MappedSuperclass
可选
@MappedSuperclass可以将超类的JPA注解传递给子类,使子类能够继承超类的JPA注解
示例:
@MappedSuperclass
publicclassEmployee(){
....
}
@Entity
publicclassEngineerextendsEmployee{
.....
}
@Entity
publicclassManagerextendsEmployee{
.....
}
14、@Embedded
可选
@Embedded将几个字段组合成一个类,并作为整个Entity的一个属性.
例如User包括id,name,city,street,zip属性.
我们希望city,street,zip属性映射为Address对象.这样,User对象将具有id,name和address这三个属性.
Address对象必须定义为@Embededable
示例:
@Embeddable
publicclassAddress{city,street,zip}
@Entity
publicclassUser{
@Embedded
publicAddressgetAddress(){
..........
}
}
现在,让我们来动手使用HibernateAnnotation。
安装HibernateAnnotation
要使用HibernateAnnotation,您至少需要具备Hibernate3.2和Java5。可以从Hibernate站点下载Hibernate3.2和HibernateAnnotation库。除了标准的HibernateJAR和依赖项之外,您还需要HibernateAnnotations.jar文件(hibernate-annotations.jar)、Java持久性API(lib/ejb3-persistence.jar)。如果您正在使用Maven,只需要向POM文件添加相应的依赖项即可,如下所示:
...
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.1.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.2.0.ga</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
...
下一步就是获取Hibernate会话工厂。尽管无需惊天的修改,但这一工作与使用HibernateAnnotations有所不同。您需要使用AnnotationConfiguration类来建立会话工厂:
sessionFactory=new
AnnotationConfiguration().buildSessionFactory();
尽管通常使用<mapping>元素来声明持久性类,您还是需要在Hibernate配置文件(通常是hibernate.cfg.xml)中声明持久性类:
<!DOCTYPEhibernate-configurationPUBLIC
"-//Hibernate/HibernateConfigurationDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mappingclass="com.onjava.modelplanes.domain.PlaneType"/>
<mappingclass="com.onjava.modelplanes.domain.ModelPlane"/>
</session-factory>
</hibernate-configuration>
近期的许多Java项目都使用了轻量级的应用框架,例如Spring。如果您正在使用Spring框架,可以使用AnnotationSessionFactoryBean类轻松建立一个基于注释的Hibernate会话工厂,如下所示:
<!--Hibernatesessionfactory-->
<beanid="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<propertyname="dataSource">
<refbean="dataSource"/>
</property>
<propertyname="hibernateProperties">
<props>
<propkey="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
<propkey="hibernate.hbm2ddl.auto">create</prop>
...
</props>
</property>
<propertyname="annotatedClasses">
<list>
<value>com.onjava.modelplanes.domain.PlaneType</value>
<value>com.onjava.modelplanes.domain.ModelPlane</value>
...
</list>
</property>
</bean>
第一个持久性类
既然已经知道了如何获得注释所支持的Hibernate会话,下面让我们来了解一下带注释的持久性类的情况:
像在其他任何Hibernate应用程序中一样,带注释的持久性类也是普通POJO。差不多可以说是。您需要向Java持久性API(javax.persistence.*)添加依赖项,如果您正在使用任何特定于Hibernate的扩展,那很可能就是HibernateAnnotation程序包(org.hibernate.annotations.*),但除此之外,它们只是具备了持久性注释的普通POJO。下面是一个简单的例子:
@Entity
publicclassModelPlane{
privateLongid;
privateStringname;
@Id
publicLonggetId(){
returnid;
}
publicvoidsetId(Longid){
this.id=id;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
}
正像我们所提到的,这非常简单。@Entity注释声明该类为持久类。@Id注释可以表明哪种属性是该类中的独特标识符。事实上,您既可以保持字段(注释成员变量),也可以保持属性(注释getter方法)的持久性。后文中将使用基于属性的注释。基于注释的持久性的优点之一在于大量使用了默认值(最大的优点就是“惯例优先原则(conventionoverconfiguration)”)。例如,您无需说明每个属性的持久性――任何属性都被假定为持久的,除非您使用@Transient注释来说明其他情况。这简化了代码,相对使用老的XML映射文件而言也大幅地减少了输入工作量。
生成主键
Hibernate能够出色地自动生成主键。Hibernate/EBJ3注释也可以为主键的自动生成提供丰富的支持,允许实现各种策略。下面的示例说明了一种常用的方法,其中Hibernate将会根据底层数据库来确定一种恰当的键生成策略:
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
publicLonggetId(){
returnid;
}
定制表和字段映射
默认情况下,Hibernate会将持久类以匹配的名称映射到表和字段中。例如,前一个类可以与映射到以如下代码创建的表中:
CREATETABLEMODELPLANE
(
IDlong,
NAMEvarchar
)
如果您是自己生成并维护数据库,那么这种方法很有效,通过省略代码可以大大简化代码维护。然而,这并不能满足所有人的需求。有些应用程序需要访问外部数据库,而另一些可能需要遵从公司的数据库命名惯例。如果有必要,您可以使用@Table和@Column注释来定制您自己的持久性映射,如下所示:
@Entity
@Table(name="T_MODEL_PLANE")
publicclassModelPlane{
privateLongid;
privateStringname;
@Id
@Column(name="PLANE_ID")
publicLonggetId(){
returnid;
}
publicvoidsetId(Longid){
this.id=id;
}
@Column(name="PLANE_NAME")
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
}
该内容将映射到下表中:
CREATETABLET_MODEL_PLANE
(
PLANE_IDlong,
PLANE_NAMEvarchar
)
也可以使用其他图和列的属性来定制映射。这使您可以指定诸如列长度、非空约束等详细内容。Hibernate支持大量针对这些注释的属性。下例中就包含了几种属性:
...
@Column(name="PLANE_ID",length=80,nullable=true)
publicStringgetName(){
returnname;
}
...
映射关系
Java持久性映射过程中最重要和最复杂的一环就是确定如何映射表间的关系。像其他产品一样,Hibernate在该领域中提供了高度的灵活性,但却是以复杂度的增加为代价。我们将通过研究几个常见案例来了解如何使用注释来处理这一问题。
其中一种最常用的关系就是多对一的关系。假定在以上示例中每个ModelPlane通过多对一的关系(也就是说,每个飞机模型只与一种飞机类型建立联系,尽管指定的飞机类型可以与七种飞机模型建立联系)来与PlaneType建立联系。可如下进行映射:
@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.MERGE})
publicPlaneTypegetPlaneType(){
returnplaneType;
}
CascadeType值表明Hibernate应如何处理级联操作。
另一种常用的关系与上述关系相反:一对多再对一关系,也称为集合。在老式的Hibernate版本中进行映射或使用注释时,集合令人头疼,这里我们将简要加以探讨,以使您了解如何处理集合,例如,在以上示例中每个PlaneType对象都可能会包含一个ModelPlanes集合。可映射如下:
@OneToMany(mappedBy="planeType",
cascade=CascadeType.ALL,
fetch=FetchType.EAGER)
@OrderBy("name")
publicList<ModelPlane>getModelPlanes(){
returnmodelPlanes;
}
命名查询
Hibernate最优秀的功能之一就在于它能够在您的映射文件中声明命名查询。随后即可通过代码中的名称调用此类查询,这使您可以专注于查询,而避免了SQL或者HQL代码分散于整个应用程序中的情况。
也可以使用注释来实现命名查询,可以使用@NamedQueries和@NamedQuery注释,如下所示:
@NamedQueries(
{
@NamedQuery(
name="planeType.findById",
query="selectpfromPlaneTypepleftjoinfetchp.modelPlaneswhereid=:id"
),
@NamedQuery(
name="planeType.findAll",
query="selectpfromPlaneTypep"
),
@NamedQuery(
name="planeType.delete",
query="deletefromPlaneTypewhereid=:id"
)
}
)
一旦完成了定义,您就可以像调用其他任何其他命名查询一样来调用它们。
结束语
Hibernate3注释提供了强大而精致的API,简化了Java数据库中的持久性代码,本文中只进行了简单的讨论。您可以选择遵从标准并使用Java持久性API,也可以利用特定于Hibernate的扩展,这些功能以损失可移植性为代价提供了更为强大的功能和更高的灵活性。无论如何,通过消除对XML映射文件的需求,Hibernate注释将简化应用程序的维护,同时也可以使您对EJB3有初步认识。来试试吧!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dingqinghu/archive/2011/03/25/6275798.aspx
注解映射必须满足两大条件:Hibernate3.2以上版本和JSEE5。
@Entity类注释,所有要持久化的类都要有
@Entity
publicclassOrgimplementsjava.io.Serializable{
}
@Id主键
@Id
@GeneratedValue
privateStringorgId;
privateStringorgName;
@Column(name="...")该属性对应表中的字段是什么,没有name表示一样
@Table对象与表映射
@UniqueConstraint唯一约束
@Version方法和字段级,乐观锁用法,返回数字和timestamp,数字为首选
@Transient暂态属性,表示不需要处理
@Basic最基本的注释。有两个属性:fetch是否延迟加载,optional是否允许null
@Enumerated枚举类型
@Temporal日期转换。默认转换Timestamp
@Lob通常与@Basic同时使用,提高访问速度。
@Embeddable类级,表可嵌入的
@Embedded方法字段级,表被嵌入的对象和@Embeddable一起使用
@AttributeOverrides属性重写
@AttributeOverride属性重写的内容和@AttributeOverrides一起嵌套使用
@SecondaryTables多个表格映射
@SecondaryTable定义辅助表格映射和@SecondaryTables一起嵌套使用
@GeneratedValue标识符生成策略,默认Auto
表与表关系映射
@OneToOne:一对一映射。它包含五个属性:
targetEntity:关联的目标类
Cascade:持久化时的级联操作,默认没有
fetch:获取对象的方式,默认EAGER
Optional:目标对象是否允许为null,默认允许
mappedBy:定义双向关联中的从属类。
单向:
@JoinColumn:定义外键(主表会多一字段,做外键)
@OneToMany:一对多映射;@ManyToOne:多对一映射
单向一对多:
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="book_oid")/**book:表;oid:book表的主键;无name会按此规则自动生成*/
单向多对一:
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="author_oid")
关联表格一对多:
@OneToMany(cascade=CascadeType.ALL)
@JoinTable(joinColumn={@JoinColumn(name="BOOK_OBJECT_OID")},inverseJoinColumns={@JoinColumn(name="AUTHER_OBJECT_OID")})
双向一对多或多对一:
不需要多一张表,只是使用mappedBy:使用在One一方,值为One方类名表示Many的从属类。
@Entity
Java代码
@Entity
publicclassOrgimplementsjava.io.Serializable{
//Fields
@Id
@GeneratedValue
privateStringorgId;
privateStringorgName;
@OneToMany(mappedBy="org")
privateList<Department>departments;
//Constructors
...
//Propertyaccessors
...
}
@EntitypublicclassOrgimplementsjava.io.Serializable{//Fields@Id@GeneratedValueprivateStringorgId;privateStringorgName;@OneToMany(mappedBy="org")privateList<Department>departments;//Constructors...//Propertyaccessors...}
@Entity
publicclassDepartmentimplementsjava.io.Serializable{
//Fields
@Id
@GeneratedValue
privateStringid;
privateStringname;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="org_orgId")
privateOrgorg;
@OneToMany(mappedBy="department")
privateList<Employee>employees;
//Constructors
publicList<Employee>getEmployees(){
returnemployees;
}
publicvoidsetEmployees(List<Employee>employees){
this.employees=employees;
}
publicOrggetOrg(){
returnorg;
}
publicvoidsetOrg(Orgorg){
this.org=org;
}
/**defaultconstructor*/
.
.
.
}
Java代码
@Entity
publicclassEmployeeimplementsjava.io.Serializable{
//Fields
@Id
@GeneratedValue
privateStringemployeeId;
privateStringemployeeName;
privateStringpassWord;
privateIntegerage;
privateIntegersex;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="department_id")
privateDepartmentdepartment;
publicDepartmentgetDepartment(){
returndepartment;
}
publicvoidsetDepartment(Departmentdepartment){
this.department=department;
}
/**defaultconstructor*/
...
//Propertyaccessors
...
}
@EntitypublicclassEmployeeimplementsjava.io.Serializable{//Fields@Id@GeneratedValueprivateStringemployeeId;privateStringemployeeName;privateStringpassWord;privateIntegerage;privateIntegersex;@ManyToOne(fetch=FetchType.EAGER)@JoinColumn(name="department_id")privateDepartmentdepartment;publicDepartmentgetDepartment(){returndepartment;}publicvoidsetDepartment(Departmentdepartment){this.department=department;}/**defaultconstructor*/...//Propertyaccessors...}
双向多对多:@ManyToMany.单向多对多这里不在赘述(没有太多实际意义)
这个比较简单,看下代码就明白了:
@Entity
publicclassBookimplementsjava.io.Serializable{
@Id
privateintid;
privateStringname;
privatefloatmoney;
@ManyToMany(cascade=CascadeType.ALL)
privateList<Author>authors;
publicList<Author>getAuthors(){
returnauthors;
}
publicvoidsetAuthors(List<Author>authors){
this.authors=authors;
}
...
}
@Entity
publicclassAuthorimplementsjava.io.Serializable{
@Id
privateintid;
privateStringname;
privateintage;
@ManyToMany(mappedBy="authors")
privateList<Book>books;
publicList<Book>getBooks(){
returnbooks;
}
publicvoidsetBooks(List<Book>books){
this.books=books;
}
...
}
基于注解的hibernate主键设置:@Id.
那么它的生成规则是什么呢?是由@GeneratedValue来规定的。
我们先来看看它是如何定义的:
Java代码
@Target({METHOD,FIELD})
@Retention(RUNTIME)
public@interfaceGeneratedValue{
GenerationTypestrategy()defaultAUTO;
Stringgenerator()default"";
}
@Target({METHOD,FIELD})@Retention(RUNTIME)public@interfaceGeneratedValue{GenerationTypestrategy()defaultAUTO;Stringgenerator()default"";}
Java代码
publicenumGenerationType{
TABLE,
SEQUENCE,
IDENTITY,
AUTO
}
publicenumGenerationType{TABLE,SEQUENCE,IDENTITY,AUTO}
现在我们看到了,它提供了4种生成策略:
TABLE:使用一个特定的数据库表格来保存标识符序列。
SEQUENCE:生成序列化标识符。
IDENTITY:标识符有数据库自动生成(主要是自动增长型)
AUTO:标识符生成工作由hibernate自动处理。实际项目开发不建议使用。
注意:当主键为int,而数据库中又不是自动增长型时,使用@GeneratedValue是无法正常工作的。
我们也可以使用下面的方式来自己指定我们的主键值:
Java代码
@GeneratedValue(generator="c-assigned")
@GenericGenerator(name="c-assigned",strategy="assigned")
privateStringemployeeId;
@GeneratedValue(generator="c-assigned")@GenericGenerator(name="c-assigned",strategy="assigned")privateStringemployeeId;
或者直接不要定义@GeneratedValue,只定义@Id效果也是一样的。