摘要:
这些年来Hibernate几乎已经成为java世界中数据库持久化方面事实上的标准它强大灵活并且性能优秀在这篇文章中我们来看一下Java 的注解功能怎么简单地用在你的hibernate代码中让你的持久化层变得更容易这些年来Hibernate几乎已经成为java世界中数据库持久化方面事实上的标准它强大灵活并且性能优秀在这篇文章中我们来看一下Java 的注解功能怎么简单地用在你的hibernate代码中让你的持久化层变得更容易
在过去Hibernate 依靠外部的XML文件来配置持久化对象数据库映射文件定义在一组XML映射文件里并且在程序开始的时候被装载有很多办法来创建这些映射文件或者自动从一个已存在的数据库模式里创建或者手动从java类对象中创建不管那种情况你都得产生一大堆Hibernate 映射文件而结束工作你也可以利用外部工具从javadocstyle 的注解中生成映射文件但这给你的开发流程增加了额外的负担
在最近的Hibernate版本里一个新的建立在Java 注解之上更为优雅的方法出现了利用新的Hibernate Annonations 库你可以发布一次如你以前的映射文件所定义的信息你猜到了注解直接嵌入你的Java类文件里注解带来了一种强大灵活地声明持久化映射的办法在最新版的几个Java集成开发环境里都很好的支持并带有代码自动完成和语法高亮功能
Hibernate annotations 也支持最新的EJB 持久化规范这些规范目的是提供一个标准的Java持久化机制当然Hibernate 也提供了更多的解决方案你能非常容易的靠近保准并且利用EJB 编程模型编写你的Hibernate持久化层
现在让我们一步步了解Hibernate Annotations
安装 Hibernate Annotations 为了使用Hibernate Annotations你需要最新的Hibernate 当然还有Java 你可以在Hibernate web site 这个网站下载Hibernate 和Hibernate Annotations库除了标准的Hibernate 库文件和必须的依赖库之外还需要下载 Hibernate Annotations库和Java 持久化API ejbpersstencejar文件如果你正在使用Maven仅仅添加相应的依赖到你的DOM文件里如下所示:
<dependency>
<groupId>orghibernate</groupId>
<artifactId>hibernate</artifactId>
<version>ga</version>
</dependency>
<dependency>
<groupId>orghibernate</groupId>
<artifactId>hibernateannotations</artifactId>
<version>ga</version>
</dependency>
<dependency>
<groupId>javaxpersistence</groupId>
<artifactId>persistenceapi</artifactId>
<version></version>
</dependency>
下一步是获得一个Hibernate Session 工厂利用Hibernate Annotations与不使用它创建Hibernate session工厂有一点不同虽然不需要大幅度修改你只需须简单地使用AnnotationConfiguration类安装你的session工厂
sessionFactory
=new AnnotationConfiguration()buildSessionFactory();
一般的你需要通过<mapping>元素在Hibernate配置文件里(hibernatecfgxml)声明持久化类
<hibernateconfiguration>
<sessionfactory>
<mapping class=comonjavamodelplanesdomainPlaneType/>
<mapping class=comonjavamodelplanesdomainModelPlane/>
</sessionfactory>
</hibernateconfiguration>
如今许多java 工程都使用轻量级的程序框架例如Spring如果你正在用Spring框架你可以容易地利用AnnotationSessionFactory类装配一个基于Annotations 的Hibernate Session Factory如下:
<! Hibernate session factory >
<bean id=sessionFactory
class=orgspringframeworkormhibernateannotationAnnotationSessionFactoryBean>
<property name=dataSource>
<ref bean=dataSource/>
</property>
<property name=hibernateProperties>
<props>
<prop key=hibernatedialect>orghibernatedialectDerbyDialect</prop>
<prop key=hibernatehbmddlauto>create</prop>
</props>
</property>
<property name=annotatedClasses>
<list>
<value>comonjavamodelplanesdomainPlaneType</value>
<value>comonjavamodelplanesdomainModelPlane</value>
</list>
</property>
</bean>
我们第一个持久化类
现在我们知道如何获得基于Annotation的Hibernate Session 让我们看看这个注解的持久化类看起来像什么样子
被注解的持久化类是一般的POJO类就像在其他Hibernate程序里的一样好的差不多了你需要依赖于Java 持久化API (javaxpersistence*)并且还需要导入注解包类(orghibernateannotations*)如果你使用了任何Hibernate扩展的话但是除此之外他们仅仅是拥有持久化相关注解的POJO这有个例子:
@Entity
public class ModelPlane {
private Long id;
private String name;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
thisid = id;
}
public String getName() {
return name;
}
public void setName(String name) {
thisname = name;
}
}
如我们所言非常简单@Entity注解声明类将被持久化@Id注解让你指示持久化类的唯一性标识属性实际上你可以持久化字段(注解成员变量)或者持久化属性(通过注释getter方法在这篇文章的剩余部分我们将用基于属性的注解关于基于注解的持久化一个好处是他的缺省行为例如你不需要声明每一个属性是否要被持久化任何属性都假定将被持久化除非用@Transient注解了他 对代码来说这是简单的并且相对于旧的XML配置文件来说也节省了很多打字量
生成主键
Hibernate一个擅长的功能是主键自动生成Hibernate/EJB 注解也为主键自动生成提供了丰富的支持允许诸多生成策略下面例子演示了最常见的用途这里Hibernate 根据数据库给出一个合适的主键生成策略
@Id
@GeneratedValue (strategy=GenerationTypeAUTO)
public Long getId() {
return id;
}
自定义表和字段映射
默认情况下Hibernate将映射持久化类到表用匹配的字段名映射例如上面的类将经由下列SQL语句映射到表:
CREATE TABLE MODELPLANE
(
ID long
NAME varchar
)
如果你自己生成和维护数据库的话非常好并且使你的代码易于维护然而他不适合所有需求有些程序需要访问外部数据库并且可能需要公司数据库命名转换如果需要的话你可以使用@Table和@Column注解进行你的持久化映射:
@Entity
@Table(name=T_MODEL_PLANE)
public class ModelPlane {
private Long id;
private String name;
@Id
@Column(name=PLANE_ID)
public Long getId() {
return id;
}
public void setId(Long id) {
thisid = id;
}
@Column(name=PLANE_NAME)
public String getName() {
return name;
}
public void setName(String name) {
thisname = name;
}
}
它将映射到下面的表
CREATE TABLE T_MODEL_PLANE
(
PLANE_ID long
PLANE_NAME varchar
)
你可以利用Table和Column属性自定义映射它可让你指定诸如列长度notnull约束等等hibernate支持大量的属性注解:
@Column(name=PLANE_ID length= nullable=true)
public String getName() {
return name;
}
…
映射关系
Java持久化映射中一个最重要最复杂的部分是确定怎么映射表间的关系如其他的特性一样Hibernate在这方面也提供了大量的灵活性但是以增加了某种复杂度为代价的我们将浏览一系列共同的用例以对如何使用注解有个大体认识
最常用的一个关系是manytoone关系假定在上面的例子中每个ModelPlane经由manytoone关系被关联到一个PlaneType (换句话说每个Model plane 被确切的关联到一个 plane type通过给定一个plane type可以被关联到多个 model plane )你可以映射如下:
@ManyToOne( cascade = {CascadeTypePERSIST CascadeTypeMERGE} )
public PlaneType getPlaneType() {
return planeType;
}
这个CascadeType值表示Hibernate将怎么进行级联操作
另外一个常用的关系是与上面相对的:onetomany关系也以集合而闻名集合将映射变得有些复杂在旧的和新的注解中并且我们将撇开表面细节直接给你完成的例子以给你一个大概例如在上面例子中每一个PlaneType对象可能包含一个ModelPlane的集合可以映射如下:
@OneToMany(mappedBy=planeType
cascade=CascadeTypeALL
fetch=FetchTypeEAGER)
@OrderBy(name)
public List<ModelPlane> getModelPlanes() {
return modelPlanes;
}
命名查询
Hibernate一个优秀的特征是可以在映射文件申明命名查询的能力这些查询可以通过名字在代码里调用这可以让你集中查询且避免有sql或者Hql代码分散在程序里
你也可以通过注解利用@NameQueries和@NameQuery注解如下:
@NamedQueries(
{
@NamedQuery(
name=planeTypefindById
query=select p from PlaneType p left join fetch pmodelPlanes where id=:id
)
@NamedQuery(
name=planeTypefindAll
query=select p from PlaneType p
)
@NamedQuery(
name=planeTypedelete
query=delete from PlaneType where id=:id
)
}
)
一旦定义可以可以调用正如其他命名查询
总结
Hibernate 注解提供了一个强大而优雅的API来简化java数据库持久化代码在这里我们仅仅涉及到表面的知识你选择贴近标准并且利用java持久化API或者收益于Hibernate的规范扩展 在以失去某种轻便性为代价的基础上它提供了更为强大灵活的功能不管怎么样通过避免了xml映射文件使用Hibernate注解可以简化你的程序维护另外的好处是指给你一个走进EJB 大门的幽径