hibernate系列十八:注解

一 简介

Hibernate提供了Hibernate Annotations扩展包,它可以替换复杂的hbm.xml文件,使得Hibernate程序的开发大大简化。即利用注解后,可不用定义持久化类对应的*.hbm.xml文件,而直接以注解方式写入持久化类的实现中。

    使用Hibernate注解,首先需要在Hibcrnate官方网站获取Annotation扩展包。使用Hibernate3.3.2需要获取的Annotations扩展包是hibernate-annotations-3.4.0.GA.zip。解压该扩展包,在目录Hibernate-annotations-3.4.0.GA\doc\reference\zh_cn\html下可以查阅关于注解的中文帮助文档。

    使用Hibernate注解的步骤如下。

    (1)添加jar包。

    ①Hibernate-annotations-3.4.O.GA根目录下的hibernate-annotations.jar。

②hibernate-annotations-3.4.O.GA\lib

目录下的Hibernate-commons-annotationsar.ejb3-persistence.jar。

    (2)使用注解配置持久化类及对象关联关系。

    (3)使用AnnotationConfiguration建立会话工厂。

    sessionFactory=new  AnnotationConfiguration().configure().buildSessionFactory();

    (4)在Hibernate配置文件(hibernate.cfg.xml)中声明持久化类。

    <mapping class="持久化类完整限定名"/>

 

二 注解配置持久类

通过表1所示注解可以完成持久化类的常用配置。

注解

含义和作用

@Entity

将一个类声明为一个持久化类

@Id

声明了持久化类的标识属性(相当于数据表的主键)

@GeneratedValue

定义标识属性值的生成策略

@Table

为持久化类映射指定表(table)、目录(catalog)和schema的名称。默认值:持久化类名,不带包名

@UniqueConstraint

定义表的唯一约束

@Lob

表示属性将被持久化为Blob或者Clob类型

@Column

将属性映射到列

@Transient

忽略这些字段和属性,不用持久化到数据库

 

     使用Hibernate注解,需要导人javax.persistence这个包,常用注解都存放在这个包中。javax.persistence包是JPA ORM规范的组成部分。JPA全称Java Persistence API,它通过JDK5.0注解或XML描述对象_关系表的映射关系,并将运行期的对象持久化到数据库中。Hibernate提供了对JPA的实现。

     @Table可以省略,默认值为持久化类名。

     @GeneratedValue指定了标识符的生成策略。JPA提供了4种标准用法。

    (1) AUTO:根据不同的数据库选择不同的策略。

    (2) TABLE:使用表保存id值。

    (3) INDENITY:使用数据库自动生成主键(主要是自动增长型,如MySql、SQL Server)。

    (4) SEQUENCE:使用序列创建主键(如Oracle)。

    Hibernate还提供了更多的ID生成器,可以通过相关资料查询。

    下面举例说明注解的使用,添加学生信息,如示例1所示。

示例1

 StudentEntity.java

   import java.util.Date;

    import javax.persistence.*;

   

    @Entity

    @Table(name="Student")

    public class StudentEntity implementsjava.io.Serializable{

        @Id

        @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seq_stu")

       @SequenceGenerator(name="seq_ stu",sequenceName="seq_stu_id",

        allocationSize=1,initialValue=1)

        private Short stuId;

        @Column(name="StuName")

        private String studentName;

        @Column(name="SchoolStartDate")

        private Date schoolStartDate

@Transient

        private DepartEntity dept;

@Transient

        private String nation;

@Transient

        private int age;

       public StudentEntity(){

       }

       //省略getter和setter方法

   }

 

hibernate.cfg.xml

<hibernate-configuration>

   <session-factory>

      <!--省略property配置-->

      <mappingclass="com.hopetech.hibernate.entity.StudentEntity" />

   </session-factory>

   </hibernate-configuration>

 

测试类代码:

   SessionFactorysf=new AnnotationConfiguration().configure()

.buildSessionFactory();

   Session session=sf.openSession();

   Transaction tx=session.beginTransaction();

   StudentEntity student=new StudentEntity();

   student.setStuName("xiaoming");

   student.setSchoolStartDate(new Date());

   session.save(student);

   tx.commit();

 

运行示例1,Hibernate执行以下SQL语句,Student表中成功添加了一条记录:

    select seq_stu_id.nextval from dual

    insert intoStudent(stuName,schoolStartDate,stuId) values(?,?,?)

 

    示例1中,StudentEntity类映射到Student表,stuId为主键,主键采用序列生成,需在数据库中创建序列Sequence,名为seq_stu_id。注解都放置在属性定义的上方。

    使用@GeneratedValue设置主键生成策略,strategy=GenerationType.SEQUENCE描述了主键生成策略为Sequence,generator="seq_stu"指定了生成器为seq_stu。

    使用@SequenceGenerator设置了序列生成器,name="seq_stu"定义了序列生成器的名称为seq_stu;sequenceName="seq_stu_id"指定了序列Sequence的名称为seq_stu_id,数据库中需创建序列Sequence,名称为seq_stu_id; initialValue=l设置了主键初始值,默认为O;allocationSize=表示预分配多少个主键值,如设置为l,表示不预分配主键值,默认为50。

    使用@Column把studentName属性映射到Student表中的StuName列。

    使用@Column把schoolStartDate属性映射到Student表中的SchoolStartDate列。

    使用@Transient把其他属性忽略,不持久化到数据库中。

在Hibernate.cfg.xml中,使用mapping元素声明持久化类。

 

三 注解配置对象管理关系

    通过表2所示注解可以完成对象关联关系的常用配置。

注解

含义和作用

@OneToOne

建立持久化类之闻的一对一关联关系

@OneToMany

建立持久化类之问的一对多关联关系

@ManyToOne

建立持久化类之间的多对一关联关系

@ManyToMany

建立持久化类之间的多对多关联关系

 

    对象关联关系中使用频率最高的是一对多(多对一)关联关系,以此为例讲解注解的配置,其他关联关系的注解配置与此类似。下面举例说明,按主键查询学生,并使用@ManyToOne加载系部,如示例2所示。

 

示例2

StudentEntity.java

    import java.util.Date;

    import javax.persistence.*;

   

    @Entity

    @Table(name="Student")

    public class StudentEntity implementsjava.io.Serializable{

        @Id

       @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seq_stu")

        @SequenceGenerator(name="seq_ stu",sequenceName="seq_stu_id",

         allocationSize=10,initialValue=1)

        private Short stuId;

        @Column(name="StuName")

        private String studentName;

        @Column(name="SchoolStartDate")

        private Date schoolStartDate

@ManyToOne

@JoinColumn(name="departId")

        private DepartEntity dept;

        public StudentEntity(){

        }

       //省略getter和setter方法

   }

 

DepartEntity.java

    @Entity

    @Table(name="Depart")

    public class DepartEntity implementsjava.io.Serializable{

       @Id

       private Integer deptId

       @Column(name="DepartName")

       private String deptName;

       //省略getter和setter方法

       public DepartEntity(){

       }

}

hibernate.cfg.xml

<hibernate-configuration>

   <session-factory>

      <!--省略property配置-->

      <mappingclass="com.hopetech.hibernate.entity.StudentEntity" />

      <mappingclass="com.hopetech.hibernate.entity.DepartEntity" />

   </session-factory>

   </hibernate-configuration>

 

测试类代码:

   SessionFactorysf=new AnnotationConfiguration().configure()

.buildSessionFactory();

   Session session=sf.openSession();

   StudentEntity student=(StudentEntity)session.load(StudentEntity.class,3);

   System.out.println(student.getStuName()+","

              +student.getDept().getDeptName());

 

运行示例2,Hibernate执行以下SQL语句,输出学生姓名和系部名称:

selects.*,d.* from Student s left outer join Depart d

ons.deptId=d.deptId where s.stuId=?

    maike,汉语研究系

 

    示例2中使用@ManyToOne配置了StudentEntity和DepartEntity类之间的多对一关联;使用@JoinColunm(name="DepartId")指定了维系关系的外键字段是Student表中的DepartId。Hibernate生成的SQL语句使用了左外连接关键字。

    下面举例说明级联的配置,添加系部的同时添加学生,如示例3所示。

示例3

StudentEntity.java和示例2相同。

DepartEntity.java

    @Entity

    @Table(name="Depart")

    public class DepartEntity implementsjava.io.Serializable{

       @Id

       private Integer deptId

       @Column(name="DepartName")

       private String deptName;

       @Transient

       private String address;

       @OneToMany(mappedBy="dept",cascade={CascadeType.ALL})

       //省略getter和setter方法

       public DepartEntity(){

       }

}

 

hibernate.cfg.xml和示例2相同。

测试类代码:

SessionFactory sf=newAnnotationConfiguration().configure()

.buildSessionFactory();

   Session session=sf.openSession();

   Transaction tx=session.beginTransaction();

   DepartEntity dept=new DepartEntity(103, "汉语研究系")

   StudentEntity student=new StudentEntity();

   student.setStuName("xiaoming");

   student.setSchoolStartDate(new Date());

   dept.getStudents().add(student);

   student.setDept(dept);

   session.save(student);

   tx.commit();

 

运行示例3,Hibernate执行以下SQL语句,保存DepartEntity对象,级联保存StudentEntity对象:

   select seq_stu_id.nextval from dual

   insert into Depart(DeptName,DeptId)values(?,?)

   insertinto Student(DeptId,StuName,SchoolStartDate,StuId) values(?,?,?,?)

 

    示例3使用@OneToMany(mappedBy="dept",cascade={CascadeType.ALL})配置了DepartEntity类和StudentEntity类之间的一对多的关系;通过cascade=(CascadeType.ALL}设置了级联;通过mappedBy="dept"设置维系关系的控制权交给StudentEntity类这一方,相当于Depart.hbm.xml中配置的inverse="true",mappedBy的属性值dept是StudentEntity类中的属性名。

    cascade属性指定级联操作:

    (1) CascadeType.REMOVE:级联删除。

    (2) CascadeType.PERSIST:persist()方法级联。

    (3) CascadeType.MERGE:级联更新。

    (4) CascadeType.REFRESH:级联刷新。

    (5) CascadeType.ALL:包含所有级联操作。

四  注解配置命名查询

使用注解可以配置命名查询。配置命名查询的注解为@NamedQuery。下面举例说明,查询姓名包含“小”字的学生,如示例4所示。

示例4

StudentEntity.java

    @Entity

@Table(name="Student")

@NamedQuery(name="selectStu",query="fromStudentEntity

where stuName like :sname")

    public class StudentEntity implementsjava.io.Serializable{

        @Id

       @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seq_stu")

        @SequenceGenerator(name="seq_ stu",sequenceName="seq_stu_id",

         allocationSize=10,initialValue=1)

        private Short stuId;

@ManyToOne(fetch=FetchType.LAZY)

@JoinColumn(name="departId")

        private DepartEntity dept;

        @Column(name="StuName")

        private String studentName;

        public StudentEntity(){

        }

       //省略getter和setter方法

   }

hibernate.cfg.xml和示例2相同。

测试类代码:

   List<StudentEntity>list=session.getNamedQuery("selectStu")

                 .setString("sname","%r%").list();

   for(StudentEntity student:list){

      System.out.println(student.getStuName());

   }

运行示例4,Hibernate执行以下SQL语句,输出了姓名包含“小”字的学生:

select* from Student where StuName like ?

张小军

刘小丽

    示例4使用@NamedQuery配置了命名查询;使用@ManyToOne(fetcl=FetchType.LAZY)配置了延迟加载。查询StudentEntity对象时,不会立即加载DepartEntity对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

御前两把刀刀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值