Hibernate Annotations

1、HibernateAnnotation依赖包

要使用HibernateAnnotation,您可以从Hibernate站点下载Hibernate3.6和HibernateAnnotation库。除了标准的HibernateJAR和依赖项之外,您还需要如下二个库:

  1.HibernateAnnotationjar文件(hibernate-annotations.jar)

  2.Java持久性API(lib/ejb3-persistence.jar)

下一步就是获取Hibernate会话工厂。近期的许多Java项目都使用了轻量级的应用框架,例如Spring。如果您正在使用Spring框架,可以使用AnnotationSessionFactoryBean类轻松建立一个基于注释的Hibernate会话工厂。

2、Hibernate注解语法

Hibernate的注解语法列表:

@Entity

声明为一个实体bean

@MappedSuperclass

用在实体的继承过程中的父类上

@Table(name="promotion_info")

为实体bean映射指定表

@Id

声明了该实体bean的标识属性

@GeneratedValue

可以定义标识字段的生成策略

@Transient

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

@Column(name="promotion_remark")

声明列,属性还包括(length=200等)

@Temporal(TemporalType.TIMESTAMP)

声明时间格式,支持DATE、TIME、 和 TIMESTAMP三种精度

@Enumerated

声明枚举

@Version

声明添加对乐观锁定的支持

@OneToOne

可以建立实体bean之间的一对一的关联

@OneToMany

可以建立实体bean之间的一对多的关联

@ManyToOne

可以建立实体bean之间的多对一的关联

@ManyToMany

可以建立实体bean之间的多对多的关联

@Formula

一个SQL表达式,这种属性是只读的,不在数据库生成属性(可以使用sum、average、max等)

@OrderBy

Many端某个字段排序(List)

详细说明:

  1.使用annotation,既可以保持字段的持久性(注释写在成员变量之上),也可以保持属性(注释写在getter方法之上)的持久性。

  2.Hibernate 能够出色地自动生成主键。Hibernate/EBJ 3 注释也可以为主键的自动生成提供丰富的支持,允许实现各种策略。其生成规则由@GeneratedValue设定的。这里的@id和@GeneratedValue都是JPA的标准用法,JPA提供的四种标准用法为TABLE、SEQUENCE、IDENTITY、AUTO。在指定主键时,如果不指定主键生成策略,默认为AUTO。

  TABLE:使用一个特定的数据库表格来保存主键。

  SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。

  IDENTITY:主键由数据库自动生成(主要是自动增长型)

  AUTO:主键由程序控制。

IDENTITY:使用SQL Server 和 MySQL 的自增字段,这个方法不能放到 Oracle 中,Oracle 不支持自增字段,要设定SEQUENCE,也可采用uuid,native等其它策略。如果要采用uuid的生成方式,由于JPA注解不支持此种方法,则要用hibernate的注解联合起来使用具体的用法如下:

@GenericGenerator(name="idGenerator", strategy="uuid") //这个是hibernate的注解
@GeneratedValue(generator="idGenerator") //使用uuid的生成策略

  3.一对多注解。使用@OneToMany注释“一”方,双向一对多时,需使用mappedBy属性标注己方为被控方。使用@ManyToOne注释“多”方,双向一对多时,需同时使用@JoinColumn(name=”外键字段”)表明己方为控制方。@OneToMany和@ManyToOne还有cascade与fetch属性。

  cascade属性可取值:
  CascadeType.PERSIST (级联新建) 
  CascadeType.REMOVE  (级联删除) 
  CascadeType.REFRESH (级联刷新) 
  CascadeType.MERGE   (级联更新)中选择一个或多个。 
  CascadeType.ALL
  fetch属性可取值:
  LAZY(默认值)采用延时加载,查询数据时,不一起查询关联对象的数据。而是当访问关联对象时(如:getStudnets()时)才触发相应的查询操作,获取关联对象数据。
  EAGER:是在查询数据时,也直接一起获取关联对象的数据。

  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定义的字段,就是当前类的主键。

  5.如果需要从父类继承公共属性,同时还不将该父类作为映射的实体(也就是该实体没有对应的表). 这个时候需要使用@MappedSuperclass注解来进行映射:

 1 @MappedSuperclass
 2 public class BaseEntity {
 3     @Basic
 4     @Temporal(TemporalType.TIMESTAMP)
 5     public Date getLastUpdate() { ... }
 6     public String getLastUpdater() { ... }
 7     ...
 8 }
 9 
10 @Entity class Order extends BaseEntity {
11     @Id public Integer getId() { ... }
12     ...
13 }
3、Spring中的配置
1 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
2     <property name="dataSource" ref="dataSource" />
3     <property name="packagesToScan">
4         <list>
5             <value>com.habuma.spitter.domain</value>
6         </list>
7     </property>
8 </bean>

4、使用示例

 1 @Entity
 2 @Table(name = "T_MODEL_PLANE")
 3 public class ModelPlane implements Serializable {
 4     @Id
 5     @Column(name = "PLANE_ID")
 6     @GeneratedValue(strategy = GenerationType.AUTO) //注解于属性中 
 7 /* 
 8 对于oracle想使用各自的Sequence,设置如下:        
 9 @GeneratedValue(strategy = GenerationType.AUTO,generator="PROMOTION_SEQ")        
10 @SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ")    
11  
12 另外:
13 对于自动增长后,在数据表中的相应字段,要设置字段为auto_increment.
14 */
15     private Long id;
16 
17     private String name;//注解写于getter方法之上.请见下. 
18 
19     //DATE            - java.sql.Date        
20     //TIME            - java.sql.Time        
21     //TIMESTAMP - java.sql.Timestamp        
22     @Temporal(TemporalType.TIMESTAMP)
23     @Column(name = "start_time")
24     private Date startTime;
25 
26     //显示0 隐藏1        
27     public static enum DisplayType {
28         显示, 隐藏
29     }
30 
31     @Enumerated(value = EnumType.ORDINAL)//ORDINAL序数        
32     private DisplayType displayType = DisplayType.显示;
33 
34     //1.sql语句中的字段和表名都应该和数据库相应,而不是类中的字段,        
35     //若带有参数如la.id= id,这个=id才是类中属性        
36     //2.操作字段一定要用别名        
37     @Formula(select COUNT(la.id) from largess la)
38     private int count;
39 
40     //注解于方法中 
41     @Column(name = "PLANE_ID", length = 80, nullable = true) //较详细定义 
42     public String getName() {
43         return name;
44     }
45 
46     public void setName(String name) {
47         this.name = name;
48     }
49 
50     其它的setter,getter省略......
51 }
52 
53 该内容将映射到下表中:
54         CREATE TABLE T_MODEL_PLANE
55         (
56         PLANE_ID long,
57         PLANE_NAME varchar
58         其它字段省略...
59         )
  1 package oneToMany; 
  2 import java.util.Set; 
  3 import javax.persistence.*; 
  4 /* 
  5 注意导入时,是导入:import javax.persistence.*;    
  6 非导入org.hibernate的相关类:import org.hibernate.annotations.Entity; 
  7 */ 
  8 @Entity 
  9 @Table(name="classes") 
 10 public class Classes implements Serializable { 
 11   @Id 
 12   @GeneratedValue(strategy=GenerationType.AUTO) 
 13   private int id; 
 14   private String name; 
 15     
 16   @OneToMany(cascade=CascadeType.ALL,mappedBy="classes")    
 17   private Set<Student> students; 
 18 //getter,setter省略 
 19 } 
 20 
 21 
 22 package oneToMany; 
 23 import javax.persistence.*; 
 24 @Entity 
 25 @Table(name="student") 
 26 public class Student implements Serializable  { 
 27   @Id 
 28   @GeneratedValue(strategy=GenerationType.AUTO) 
 29   private int sid; 
 30     
 31   private String sname; 
 32     
 33   //若有多个cascade,可以是:{CascadeType.PERSIST,CascadeType.MERGE} 
 34   @ManyToOne(cascade={CascadeType.ALL})         
 35   @JoinColumn(name="classid")     //student类中对应外键的属性:classid 
 36   private Classes classes; 
 37 //getter,setter省略 
 38 } 
 39 
 40 
 41 public class TestOneToMany { 
 42 /* 
 43 CREATE TABLE    student (    --要定义外键!!!!!!! 
 44     `sid` double NOT NULL auto_increment, 
 45     `classid` double NULL, 
 46     `sname` varchar(255) NOT NULL, 
 47     PRIMARY KEY    (sid), 
 48     INDEX par_ind (classid), 
 49     FOREIGN KEY (classid) REFERENCES classes(id) ON DELETE CASCADE ON UPDATE CASCADE 
 50 ) ENGINE=InnoDB 
 51 */    
 52   public static void main(String[] args) throws SQLException    
 53   { 
 54     try 
 55     { 
 56       SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory(); 
 57       Session session=sf.openSession(); 
 58       Transaction tx=session.beginTransaction();         
 59 /*
 60 因为mappedBy是定义在classes中,即classes类不负责维护级联关系.即维护者是student.所以,
 61 1.要将clsses的数据,赋给student,即用student的setClasses()方法去捆定class数据;
 62 2.在进行数据插入/更新session.save()/session.update()时,最后操作的是student.
 63 */
 64       Classes classes=new Classes(); 
 65       classes.setName("access"); 
 66         
 67       Student st1=new Student(); 
 68       st1.setSname("jason"); 
 69       st1.setClasses(classes); 
 70       session.save(st1); 
 71         
 72       Student st2=new Student(); 
 73       st2.setSname("hwj"); 
 74       st2.setClasses(classes); 
 75       session.save(st2); 
 76       tx.commit();
 77 /* 
 78 输出如下:
 79 Hibernate: insert into classes (name) values (?)
 80 Hibernate: insert into student (classid, sname) values (?, ?)
 81 Hibernate: insert into student (classid, sname) values (?, ?)
 82 */
 83 /*
 84 因为一端维护关系另一端不维护关系的原因,我们必须注意避免在应用中用不维护关系的类(class)建立关系,因为这样建立的关系是不会在数据库中存储的。
 85 如上的代码倒过来,则插入时,student的外键值为空.如下:
 86 */
 87 //      Student st1=new Student(); 
 88 //      st1.setSname("jason"); 
 89 //      session.save(st1); 
 90 //        
 91 //      Student st2=new Student(); 
 92 //      st2.setSname("hwj"); 
 93 //      session.save(st2); 
 94 //        
 95 //      Set<Student> students=new HashSet<Student>(); 
 96 //      students.add(st1); 
 97 //      students.add(st2); 
 98 //        
 99 //      Classes classes=new Classes(); 
100 //      classes.setName("access"); 
101 //      classes.setStudents(students); 
102 //      session.save(classes); 
103 /*
104 输出如下:
105 Hibernate: insert into student (classid, sname) values (?, ?)
106 Hibernate: insert into student (classid, sname) values (?, ?)
107 Hibernate: insert into classes (name) values (?)
108 */
109     } 
110     catch(HibernateException e) 
111     { 
112       e.printStackTrace();        
113     } 
114   } 
115 }
 1 @Entity 
 2 @Table(name="jcourse") 
 3 public class Jcourse { 
 4   @Id 
 5   @GeneratedValue(strategy=GenerationType.AUTO) 
 6   private int cid; 
 7   private String cname; 
 8     
 9   @ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.LAZY ,mappedBy="courses") 
10   private Set<Jstudent> students; 
11 //setter,getter省略....    
12 } 
13 
14 
15 @Entity 
16 @Table(name="jstudent") 
17 public class Jstudent { 
18   @Id 
19   @GeneratedValue(strategy=GenerationType.AUTO) 
20   private int sid; 
21     
22   private String sname; 
23     
24   @ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE},fetch=FetchType.EAGER) 
25   //inverseJoinColumns中对应的id为以下属性course的对应id. 
26   @JoinTable(name="j_student_course" ,joinColumns={@JoinColumn(name="sid")},inverseJoinColumns={@JoinColumn(name="cid")}) 
27   private Set<Jcourse> courses; 
28 //setter,getter省略....    
29 } 
30 
31 
32 public class Test { 
33   public static void main(String[] args) { 
34     try 
35     { 
36       SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory(); 
37       Session session=sf.openSession(); 
38       Transaction tx=session.beginTransaction(); 
39         
40       Jcourse course=new Jcourse(); 
41       course.setCname("jason-english"); 
42       session.save(course); //先各自保存. 
43         
44       Jcourse course2=new Jcourse(); 
45       course2.setCname("herry-english"); 
46       session.save(course2); 
47         
48       Set<Jcourse> courses=new HashSet<Jcourse>(); 
49       courses.add(course); 
50       courses.add(course2); 
51         
52       Jstudent student=new Jstudent(); 
53       student.setSname("jason"); 
54       student.setCourses(courses); 
55         
56       session.save(student);// 要用非mapby定义的类(studet)来作为主者(会控制级联关系),一对多,多对一也一样道理. 
57       //可以尝试反过来. 
58       tx.commit(); 
59     } 
60     catch(HibernateException e) 
61     { 
62       e.printStackTrace();        
63     } 
64   } 
65 }

 5、参考:

  http://blog.csdn.net/xingfeng0501/article/details/7005917

  http://docs.jboss.org/hibernate/annotations/3.4/reference/zh_cn/html_single/

posted @ 2015-02-24 19:11  添哥  阅读(433)  评论(0编辑  收藏  举报