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属性。
CascadeType.REMOVE (级联删除)
CascadeType.REFRESH (级联刷新)
CascadeType.MERGE (级联更新)中选择一个或多个。
CascadeType.ALL
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 }
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/