服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

hibernate 3 annotations 进阶

  摘要:
    这些年来,hibernate几乎已经成为java世界中数据库持久化方面事实上的标准,它强大灵活并且性能优秀.在这篇文章中,我们来看一下java 5的注解功能怎么简单地用在你的hibernate代码中让你的持久化层变得更容易.这些年来,hibernate几乎已经成为java世界中数据库持久化方面事实上的标准,它强大灵活并且性能优秀.在这篇文章中,我们来看一下java 5的注解功能怎么简单地用在你的hibernate代码中让你的持久化层变得更容易.

    在过去,hibernate 依靠外部的xml文件来配置持久化对象,数据库映射文件定义在一组xml映射文件里并且在程序开始的时候被装载.有很多办法来创建这些映射文件,或者自动从一个已存在的数据库模式里创建,或者手动从java类对象中创建.不管那种情况,你都得产生一大堆hibernate 映射文件而结束工作.,你也可以利用外部工具从javadoc-style 的注解中生成映射文件,但这给你的开发流程增加了额外的负担.

    在最近的hibernate版本里,一个新的建立在java 5 注解之上更为优雅的方法出现了.利用新的hibernate annonations 库,你可以发布一次如你以前的映射文件所定义的信息,你猜到了-注解直接嵌入你的java类文件里.注解带来了一种强大灵活地声明持久化映射的办法.在最新版的几个java集成开发环境里都很好的支持,并带有代码自动完成和语法高亮功能.

    hibernate annotations 也支持最新的ejb 3持久化规范,这些规范目的是提供一个标准的java持久化机制.当然hibernate 3也提供了更多的解决方案,你能非常容易的靠近保准并且利用ejb 3编程模型编写你的hibernate持久化层.

    现在让我们一步步了解hibernate annotations.
安装 hibernate annotations

    为了使用hibernate annotations,你需要最新的hibernate 3.2 ,当然还有java 5 你可以在hibernate web site 这个网站下载hibernate 3.2和hibernate annotations库.除了标准的hibernate 库文件和必须的依赖库之外,还需要下载 hibernate annotations库和java 持久化api ---ejb3-persstence.jar文件.如果你正在使用maven,仅仅添加相应的依赖到你的dom文件里,如下所示:

 ...
    <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 session 工厂.利用hibernate annotations与不使用它创建hibernate session工厂有一点不同,虽然不需要大幅度修改.你只需须简单地使用annotationconfiguration类安装你的session工厂:
    

sessionfactory
=new annotationconfiguration().buildsessionfactory();



一般的,你需要通过<mapping>元素在hibernate配置文件里(hibernate.cfg.xml)声明持久化类
  



        <hibernate-configuration>
          <session-factory>
            <mapping class="com.onjava.modelplanes.domain.planetype"/>
            <mapping class="com.onjava.modelplanes.domain.modelplane"/>
          </session-factory>
  </hibernate-configuration>



    如今许多java 工程都使用轻量级的程序框架例如spring.如果你正在用spring框架,你可以容易地利用annotationsessionfactory类装配一个基于annotations 的hibernate session factory,如下:

<!-- hibernate session factory -->
  <bean id="sessionfactory"
class="org.springframework.orm.hibernate3.annotation.annotationsessionfactorybean">
   <property name="datasource">
     <ref bean="datasource"/>
   </property>
   <property name="hibernateproperties">
     <props>
       <prop key="hibernate.dialect">org.hibernate.dialect.derbydialect</prop>
       <prop key="hibernate.hbm2ddl.auto">create</prop>
       ...
     </props>
   </property>
   <property name="annotatedclasses">
     <list>
       <value>com.onjava.modelplanes.domain.planetype</value>
       <value>com.onjava.modelplanes.domain.modelplane</value>
       ...
     </list>
   </property>
</bean>
我们第一个持久化类

    现在我们知道如何获得基于annotation的hibernate session ,让我们看看这个注解的持久化类看起来像什么样子.
    被注解的持久化类是一般的pojo类,就像在其他hibernate程序里的一样.好的,差不多了.你需要依赖于java 持久化api (javax.persistence.*),并且还需要导入注解包类(org.hibernate.annotations.*)如果你使用了任何hibernate扩展的话.但是除此之外,他们仅仅是拥有持久化相关注解的pojo.这有个例子:

@entity
public class modelplane {

    private long id;
    private string name;
    
    @id
    public long getid() {
        return id;
    }

    public void setid(long id) {
        this.id = id;
    }

    public string getname() {
        return name;
    }

    public void setname(string name) {
        this.name = name;
}
}



    如我们所言,非常简单.@entity注解声明类将被持久化.@id注解让你指示持久化类的唯一性标识属性.实际上,你可以持久化字段(注解成员变量)或者持久化属性(通过注释getter方法.在这篇文章的剩余部分,我们将用基于属性的注解.关于基于注解的持久化一个好处是他的缺省行为.例如.你不需要声明每一个属性是否要被持久化-任何属性都假定将被持久化除非用@transient注解了他. 对代码来说这是简单的,并且相对于旧的xml配置文件来说,也节省了很多打字量.

生成主键

    hibernate一个擅长的功能是主键自动生成,hibernate/ejb 3注解也为主键自动生成提供了丰富的支持,允许诸多生成策略.下面例子演示了最常见的用途,这里hibernate 根据数据库给出一个合适的主键生成策略.

    @id
    @generatedvalue (strategy=generationtype.auto)
    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) {
        this.id = id;
    }

    @column(name="plane_name")
    public string getname() {
        return name;
    }

    public void setname(string name) {
        this.name = name;
}
}



它将映射到下面的表

create table t_model_plane 
(
    plane_id long,
plane_name varchar
)



    你可以利用table和column属性自定义映射.它可让你指定诸如列长度,not-null约束等等,hibernate支持大量的属性注解:

...
    @column(name="plane_id", length=80, nullable=true)
    public string getname() {
        return name;
}
映射关系

    java持久化映射中一个最重要,最复杂的部分是确定怎么映射表间的关系.如其他的特性一样,hibernate在这方面也提供了大量的灵活性,但是以增加了某种复杂度为代价的.我们将浏览一系列共同的用例以对如何使用注解有个大体认识.
最常用的一个关系是many-to-one关系.假定在上面的例子中,每个modelplane经由many-to-one关系被关联到一个planetype (换句话说每个model plane 被确切的关联到一个 plane type,通过给定一个plane type可以被关联到多个 model plane ),你可以映射如下:

   @manytoone( cascade = {cascadetype.persist, cascadetype.merge} )
    public planetype getplanetype() {
                    return planetype;
          }



    这个cascadetype值表示hibernate将怎么进行级联操作
    另外一个常用的关系是与上面相对的:one-to-many关系,也以集合而闻名,集合将映射变得有些复杂,在旧的和新的注解中,并且我们将撇开表面细节直接给你完成的例子以给你一个大概,例如在上面例子中,每一个planetype对象可能包含一个modelplane的集合,可以映射如下:

    @onetomany(mappedby="planetype",
                   cascade=cascadetype.all,
                   fetch=fetchtype.eager)
    @orderby("name")
    public list<modelplane> getmodelplanes() {
        return modelplanes;
}



命名查询
    hibernate一个优秀的特征是可以在映射文件申明命名查询的能力.这些查询可以通过名字在代码里调用,这可以让你集中查询且避免有sql或者hql代码分散在程序里.

你也可以通过注解,利用@namequeries和@namequery注解,如下:

@namedqueries(
{        
  @namedquery(
    name="planetype.findbyid",
    query="select p from planetype p left join fetch p.modelplanes where id=:id"
  ),
  @namedquery(
    name="planetype.findall",
    query="select p from planetype p"
  ),
  @namedquery(
          name="planetype.delete",
          query="delete from planetype where id=:id"
        )  
}
)



一旦定义,可以可以调用正如其他命名查询.

总结

    hibernate 3注解提供了一个强大而优雅的api来简化java数据库持久化代码,在这里我们仅仅涉及到表面的知识,你选择贴近标准,并且利用java持久化api或者收益于hibernate的规范扩展, 在以失去某种轻便性为代价的基础上,它提供了更为强大灵活的功能.不管怎么样,通过避免了xml映射文件.使用hibernate注解可以简化你的程序维护,另外的好处是指给你一个走进ejb 3大门的幽径.

扫描关注微信公众号