`

hibernate Annotation类的操作

阅读更多

简介:
在过去几年里,Hibernate不断发展,几乎成为Java数据库持久性的事实标准。它非常强大、灵活,而且具备了优异的性能。在本文中,我们将了解如何使用Java 5 注释来简化Hibernate代码,并使持久层的编码过程变得更为轻松。
  传统上,Hibernate的配置依赖于外部 XML 文件:数据库映射被定义为一组 XML 映射文件,并且在启动时进行加载。
    在最近发布的几个Hibernate版本中,出现了一种基于 Java 5 注释的更为巧妙的新方法。借助新的 Hibernate Annotation 库,即可一次性地分配所有旧映射文件——一切都会按照您的想法来定义——注释直接嵌入到您的Java 类中,并提供一种强大及灵活的方法来声明持久性映射。

即利用hibernate注解后,可不用定义持久化类对应的*.hbm.xml文件,直接以注解方式写入在持久化类中来实现。
Hibernate annotation使用了ejb JPA的注解,所以,下面安装配置hibernate annotation环境时,需要导入ejb的包。许多网上的资料都是jpa hibernate annotation方面的资料。
(2)
安装 Hibernate Annotation
第一步,
环境与jar包:
  要使用 Hibernate Annotation,您至少需要具备 Hibernate 3.2和Java 5。可以从 Hibernate 站点下载 Hibernate 3.2 和 Hibernate Annotation库。除了标准的 Hibernate JAR 和依赖项之外,您还需要 Hibernate Annotations .jar 文件(hibernate-annotations.jar)、Java 持久性 API (lib/ejb3-persistence.jar)。
添加hibernate3.2.jar,hibernate-annotations-3.3.0.jar,hibernate-commons-annotations.jar和ejb3-persistence.jar 。这样就可以使用hibernate的annotation了。

如果您正在使用 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 会话工厂。尽管无需惊天的修改,但这一工作与使用 Hibernate Annotations有所不同。您需要使用 AnnotationConfiguration 类来建立会话工厂:
sessionFactory = new AnnotationConfiguration().buildSessionFactory();
第三步,
尽管通常使用 <mapping> 元素来声明持久性类,您还是需要在 Hibernate 配置文件(通常是 hibernate.cfg.xml)中声明持久性类:
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
        <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 框架,可以使用
AnnotationSessionFactoryBean 类轻松建立一个基于注释的 Hibernate 会话工厂,如下所示:
<!-- 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>
(3)
hibernate Annotation标签的使用:
[1]
1.带注释的持久性类也是普通 POJO,它们只是具备了持久性注释的普通 POJO 。
2.事实上,您既可以保持字段的持久性(注释写在成员变量之上),也可以保持属性(注释写在getter方法之上)的持久性。
3.常用的hibernate annotation标签如下:
@Entity               --注释声明该类为持久类。将一个Javabean类声明为一个实体的数据库表映射类,最好实现序列化.此时,默认情况下,所有的类属性都为映射到数据表的持久性字段.若在类中,添加另外属性,而非映射来数据库的,要用下面的Transient来注解.

@Table(name="promotion_info")      --持久性映射的表(表名="promotion_info).@Table是类一级的注解,定义在@Entity下,为实体bean映射表,目录和schema的名字,默认为实体bean的类名,不带包名.

@Id--注释可以表明哪种属性是该类中的独特标识符(即相当于数据表的主键)。
@GeneratedValue --定义自动增长的主键的生成策略.
@Transient            --将忽略这些字段和属性,不用持久化到数据库.适用于,在当前的持久类中,某些属性不是用于映射到数据表,而是用于其它的业务逻辑需要,这时,须将这些属性进行transient的注解.否则系统会因映射不到数据表相应字段而出错.
@Temporal(TemporalType.TIMESTAMP)--声明时间格式
@Enumerated          --声明枚举
@Version                --声明添加对乐观锁定的支持
@OneToOne             --可以建立实体bean之间的一对一的关联
@OneToMany           --可以建立实体bean之间的一对多的关联
@ManyToOne           --可以建立实体bean之间的多对一的关联
@ManyToMany         --可以建立实体bean之间的多对多的关联
@Formula                --一个SQL表达式,这种属性是只读的,不在数据库生成属性(可以使用sum、average、max等)
@OrderBy                --Many端某个字段排序(List)
1.2
Hibernate 能够出色地自动生成主键。Hibernate/EBJ 3 注释也可以为主键的自动生成提供丰富的支持,允许实现各种策略。
其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法, JPA提供四种标准用法,由@GeneratedValue的源代码可以明显看出.
JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO.
TABLE:使用一个特定的数据库表格来保存主键。
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
IDENTITY:主键由数据库自动生成(主要是自动增长型)
AUTO:主键由程序控制。
在指定主键时,如果不指定主键生成策略,默认为AUTO。
@Id
相当于
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
identity:
使用SQL Server 和 MySQL 的自增字段,这个方法不能放到 Oracle 中,Oracle 不支持自增字段,要设定sequence(MySQL 和 SQL Server 中很常用)。
Oracle就要采用sequence了.
同时,也可采用uuid,native等其它策略.(相关用法,上网查询)
[2]
第一个持久性类
@Entity
@Table(name="T_MODEL_PLANE")
public class ModelPlane    implements Serializable {
         @Id
         @Column(name="PLANE_ID")    
         @GeneratedValue(strategy=GenerationType.AUTO) //注解于属性中
/*
对于oracle想使用各自的Sequence,设置如下:        
@GeneratedValue(strategy = GenerationType.AUTO,generator="PROMOTION_SEQ")        
@SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ")    
另外:
对于自动增长后,在数据表中的相应字段,要设置字段为auto_increment.
*/

        private Long id;

        private String name;//注解写于getter方法之上.请见下.

     //DATE             - java.sql.Date        
     //TIME             - java.sql.Time        
     //TIMESTAMP - java.sql.Timestamp        
     @Temporal(TemporalType.TIMESTAMP)        
     @Column(name="start_time")        
     private Date startTime;    

     //显示0 隐藏1        
     public static enum DisplayType {显示,隐藏}        
     @Enumerated(value = EnumType.ORDINAL)//ORDINAL序数        
     private DisplayType displayType = DisplayType.显示;    

        //1.sql语句中的字段和表名都应该和数据库相应,而不是类中的字段,        
     //若带有参数如la.id= id,这个=id才是类中属性        
     //2.操作字段一定要用别名        
     @Formula(select COUNT(la.id) from largess la)        
     private int count;    

        //注解于方法中
         @Column(name="PLANE_ID", length=80, nullable=true) //较详细定义
        public String getName() {
                return name;
         }
        public void setName(String name) {
                this.name = name;
         }
其它的setter,getter省略......
}

该内容将映射到下表中:
CREATE TABLE T_MODEL_PLANE
(
         PLANE_ID long,
         PLANE_NAME varchar
         其它字段省略...
)    
默认情况下,Hibernate 会将持久类以匹配的名称映射到表和字段中。例如,下例中,若不用注解,则会映射到如下一表中:
CREATE TABLE MODELPLANE
(
    ID long,
    NAME varchar
    其它字段省略...
)
[3]
一对多注解:
1.
在一对多注解中,会用到:
"一"方:
@OneToMany --> mappedBy:"多"方的关联属性(被控方)
"多"方:
@ManyToOne --> @JoinColumn,"多"方定义的外键字段.
如数据表定义外键如下:
FOREIGN KEY (classid) REFERENCES classes(id)
则:
@JoinColumn(name="classid")
2.
在双向关联中,有且仅有一端作为主体(owner)端存在:主体端负责维护联接列(即更新),对于不需要维护这种关系的从表则通过mappedNy属性进行声明。mappedBy的值指向另一主体的关联属性。例子中,mappedBy的值为classes。
附加说明:
mappedBy相当于过去的inverse="true".
inverse=false的side(side其实是指inverse=false所位于的class元素)端有责任维护关系,而inverse=true端无须维护这些关系。
3.
cascade与fetch使用说明:
Cascade
CascadeType.PERSIST (级联新建)
CascadeType.REMOVE (级联删除)
CascadeType.REFRESH (级联刷新)
CascadeType.MERGE   (级联更新)中选择一个或多个。
CascadeType.ALL
fetch属性:
关联关系获取方式,即是否采用延时加载。
LAZY(默认值)采用延时加载,查询数据时,不一起查询关联对象的数据。而是当访问关联对象时(如:getStudnets()时)才触发相应的查询操作,获取关联对象数据。
EAGER:是在查询数据时,也直接一起获取关联对象的数据。
package oneToMany;
import java.util.Set;
import javax.persistence.*;
/*
注意导入时,是导入:import javax.persistence.*;    
非导入org.hibernate的相关类:import org.hibernate.annotations.Entity;
*/

@Entity
@Table(name="classes")
public class Classes implements Serializable {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
  private int id;
  private String name;
    
   @OneToMany(cascade=CascadeType.ALL,mappedBy="classes")    
  private Set<Student> students;
//getter,setter省略
}


package oneToMany;
import javax.persistence.*;
@Entity
@Table(name="student")
public class Student implements Serializable   {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
  private int sid;
    
  private String sname;
    
  //若有多个cascade,可以是:{CascadeType.PERSIST,CascadeType.MERGE}
   @ManyToOne(cascade={CascadeType.ALL})        
   @JoinColumn(name="classid")     //student类中对应外键的属性:classid
  private Classes classes;
//getter,setter省略
}


public class TestOneToMany {
/*
CREATE TABLE     student (     --要定义外键!!!!!!!
     `sid` double NOT NULL auto_increment,
     `classid` double NULL,
     `sname` varchar(255) NOT NULL,
     PRIMARY KEY     (sid),
     INDEX par_ind (classid),
     FOREIGN KEY (classid) REFERENCES classes(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB
*/
    
  public static void main(String[] args) throws SQLException    
   {
    try
     {
       SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
       Session session=sf.openSession();
       Transaction tx=session.beginTransaction();         
/*
因为mappedBy是定义在classes中,即classes类不负责维护级联关系.即维护者是student.所以,
1.要将clsses的数据,赋给student,即用student的setClasses()方法去捆定class数据;
2.在进行数据插入/更新session.save()/session.update()时,最后操作的是student.
*/
       Classes classes=new Classes();
       classes.setName("access");
        
       Student st1=new Student();
       st1.setSname("jason");
       st1.setClasses(classes);
       session.save(st1);
        
       Student st2=new Student();
       st2.setSname("hwj");
       st2.setClasses(classes);
       session.save(st2);
       tx.commit();
/*
输出如下:
Hibernate: insert into classes (name) values (?)
Hibernate: insert into student (classid, sname) values (?, ?)
Hibernate: insert into student (classid, sname) values (?, ?)
*/
/*
因为一端维护关系另一端不维护关系的原因,我们必须注意避免在应用中用不维护关系的类(class)建立关系,因为这样建立的关系是不会在数据库中存储的。
如上的代码倒过来,则插入时,student的外键值为空.如下:
*/
//       Student st1=new Student();
//       st1.setSname("jason");

//       session.save(st1);
//        
//       Student st2=new Student();
//       st2.setSname("hwj");
//       session.save(st2);
//        
//       Set<Student> students=new HashSet<Student>();
//       students.add(st1);
//       students.add(st2);
//        
//       Classes classes=new Classes();
//       classes.setName("access");
//       classes.setStudents(students);
//       session.save(classes);
/*
输出如下:
Hibernate: insert into student (classid, sname) values (?, ?)
Hibernate: insert into student (classid, sname) values (?, ?)
Hibernate: insert into classes (name) values (?)
*/
     }
    catch(HibernateException e)
     {
       e.printStackTrace();        
     }
   }
}
[4]
多对多注解:
在多对多注解中,双方都采用@ManyToMany.
其中被控方,像一对多注解中设置一样,也要设置mappedBy.
其中主控方,不像一对多注解那样,采用@joinColumn,而是采用@joinTable.如下:
@JoinTable(name="j_student_course" ,joinColumns={@JoinColumn(name="sid")},inverseJoinColumns={@JoinColumn(name="cid")})
其中,
如上所说,mappedBy,相当于inverse="true".所以,在@joinTable中的inverseJoinColumns中定义的字段为mappedBy所在类的主键.
joinColumns定义的字段,就是当前类的主键.
@Entity
@Table(name="jcourse")
public class Jcourse {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
  private int cid;
  private String cname;
    
   @ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.LAZY ,mappedBy="courses")
  private Set<Jstudent> students;
//setter,getter省略....    
}


@Entity
@Table(name="jstudent")
public class Jstudent {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
  private int sid;
    
  private String sname;
    
   @ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.EAGER)
  //inverseJoinColumns中对应的id为以下属性course的对应id.
   @JoinTable(name="j_student_course" ,joinColumns={@JoinColumn(name="sid")},inverseJoinColumns={@JoinColumn(name="cid")})
  private Set<Jcourse> courses;
//setter,getter省略....    
}


public class Test {
  public static void main(String[] args) {
    try
     {
       SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
       Session session=sf.openSession();
       Transaction tx=session.beginTransaction();
        
       Jcourse course=new Jcourse();
       course.setCname("jason-english");
       session.save(course); //先各自保存.
        
       Jcourse course2=new Jcourse();
       course2.setCname("herry-english");
       session.save(course2);
        
       Set<Jcourse> courses=new HashSet<Jcourse>();
       courses.add(course);
       courses.add(course2);
        
       Jstudent student=new Jstudent();
       student.setSname("jason");
       student.setCourses(courses);
        
       session.save(student);// 要用非mapby定义的类(studet)来作为主者(会控制级联关系),一对多,多对一也一样道理.
      //可以尝试反过来.
       tx.commit();
     }
    catch(HibernateException e)
     {
       e.printStackTrace();        
     }
   }
}

 

分享到:
评论

相关推荐

    Hibernate Annotation 学习笔记

    一步步hibernate annotation练习笔记, 实例操作,从经验中学习

    Hibernate_Annotation关联映射

    Hibernate Annotation几种关联映射 一对一(One-To-One) 使用@OneToOne注解建立实体Bean之间的一对一关联。一对一关联有三种情况:(1).关联的实体都共享同样的主键,(2).其中一个实体通过外键关联到另一个实体的主键...

    struts2+spring+hibernate(实现XML和Annotation两种方式操作数据库)

    struts2+spring+hibernate(实现XML和Annotation两种方式操作数据库) 项目描述: 框架及版本:struts2 + spring3.0 + hibernate3.3 所实现的功能说明 把两个对象存入到数据库中 1、一种方法采用XML文件映射的方式 2...

    hibernate demo

    hibernate annotation 操作数据库包括对数据库的增删改查,其中包括HQL SQL OBC 等查询,部署上去就可以用,很好用的学习hibernate anntation demo

    hibernate应用[包括示例,映射,主键自增,各种查询操作方式以及配置文档以及 Annotation示例]

    hibernate应用[包括示例,映射,主键自增,各种查询操作方式以及配置文档以及Annotation示例]

    hibernate笔记

    3 hibernate annotation references 5 环境准备 5 1 下载hibernate-distribution-3.3.2.GA-dist 5 2 下载hibernate-annotations-3[1].4.0.GA 5 3 注意阅读hibernate compatibility matrix(hibernate 网站download) 5...

    基于Maven,Struts2, Spring,Hibernate全注释的开发框架

    存贮过程进行操作,目前还有待完善,可以不用hibernate-generic-dao - Generic DAO, 用Spring3.2.0和Hibernate4替换,就是一个非常好的Struts2+Spring3+Hibernate4基于annotation的零配置的开发框架 借鉴网友的经验...

    马士兵hibernate学习笔记(原版)

    3 重Annotation,轻xml配置文件 ... 性能优化 1 注意session.clear()的运用,尤其在不断分页循环的时候 2 1+N问题 (典型的面试题) (详见 hibernate_2800_Hibernate_1+N项目) 3 list和iterate不同之处(//主要...

    Spring3+Struts2+Hibernate3 全注解集成开发

    Spring3Annotation+Struts2Annotation+Hibernate3Annotation 全注解集成开发,操作Emp表

    android-sqlite-hibernate

    2. sqlite-java-tool pc端(包括windows,linux,mac)下的sqlite数据库操作工具,该工具是基于sqlite-annotation-convention插件的,实现了许多常用的操作,你也可以直接编写sql代码,然后通过该工具执行。

    Hibernate+中文文档

    5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...

    jsf1.2+spring3.0+hibernate3.3例子-单表增删改查

    使用jsf1.2+spring3.0+hibernate3.3实现集成,利用annotation实现自动对象管理注入,用户表的登录增删改查操作,包括验证码ajax集成,消息机制,国际化处理,自定义转换器,自定义验证器等 qq:38732796 欢迎讨论

    hibernate3.2中文文档(chm格式)

    5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...

    HibernateAPI中文版.chm

    5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...

    Hibernate中文详细学习文档

    5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...

    Hibernate 中文 html 帮助文档

    5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) ...

    最全Hibernate 参考文档

    5.4.2. 使用 JDK 5.0 的注解(Annotation) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) 6.2. 集合映射( Collection mappings ) 6.2.1. 集合外键(Collection foreign keys) 6.2.2. 集合...

    hibernate 体系结构与配置 参考文档(html)

    使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) ...

    Hibernate教程

    6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent collections) 7.2. 集合映射( Collection mappings ) 7.2.1. 集合外键(Collection foreign keys) 7.2.2. ...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...

Global site tag (gtag.js) - Google Analytics