使用注解的目的

为了简化繁琐的ORM映射文件(*.hbm.xml)的配置

JPA与Hibernate的关系

什么是JPA?
JPA即Java Persistence API
JPA注解是JavaEE的规范和标准

JPA与Hibernate的关系
JPA是标准接口,Hibernate是实现,但是其功能是JPA的超集,即HIbernate更强大

Hibernate如何实现与JPA的关系
通过hibernate-annotation、hibernate-entityManager、hibernate-core三个组件实现

注意:一般在实际开发中,优先考虑使用JPA注解,这样更有利于程序的移植性和扩展

Hibernate注解的分类

  • 类级别注解
  • 属性级别注解
  • 映射关系注解

常见的类级别注解

@Entity 表示一个实体类,对应数据库中的一张表
@Table 表示表
@Embeddable 表示一个嵌入类

@Entity:映射实体类

  • @Entity(name=”tableName”)
  • name:可选,对应数据库中的一张表,若表名与实体类名相同,可省略
  • 注意:使用@Entity时必须指定实体类的主键属性
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity(name="t_student")
public class Student

@Id//设置主键
private int id;

private

@Table(name=”“,catalog=”“,schema=”“)

  • 与@Entity配合使用,只能标注在实体的class定义处,表示实体对应的数据库表的信息
  • name:可选,映射表的名称,默认表名与实体名一致,只有在不一致的情况下才需要指定表名
  • catalog:可选,表示catalog名称,默认为catalog(“”)
  • schema:可选,表示schema名称,默认为schema(“”)
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name="t_student")
@Entity
public class Student

@Id//设置主键
private int id;

private

@Embeddable

  • 表示一个非Entity类可以嵌入到另一个Entity类中作为属性而存在,不对应数据库中的一张表
import javax.persistence.Embeddable;

@Embeddable
public class Address

private String address;

private

Hibernate属性级别注解

添加方式

  • 写在属性字段上面
  • 写在属性的get访问器的上面

@Id

  • 必须,定义了映射到数据库表的主键的属性,一个实体类可以有一个或多个属性被映射为主键,可置于主键属性或get方法前
  • 若果有多个属性定义为主键属性,该实体类必须实现Serializable接口
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name="t_student")
@Entity
public class Student implements Serializable{

private static final long serialVersionUID = -5577849458641751334L;

@Id//设置主键
private int id;

@Id
@Column(length=8)//若String类型为主键,长度不能过长
private

@GeneratedValue(strategy=GenerationType.AUTO,generator=”“)

  • 可选,用于定义主键生成策略
  • strategy表示主键生成策略,取值有以下几种
  • GenerationType.AUTO:根据底层数据库自动选择(默认)
  • GenerationType.INDENTITY:根据数据库的Identity字段生成
  • GenerationType.SEQUENCE:使用sequence来决定主键的取值
  • GenerationType.TABLE:使用指定表来决定主键取值,结合@TableGenerator使用
@Id//设置主键
@TableGenerator(name="tab_cat",allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE)
private int

Generator表示主键生成器的名称,这个属性通常和ORM框架有关
eg:Hibernate可以指定uuid等生成主键

  • 指定主键生成策略为手动指定主键的值
@Id
@GeneratedValue(generator="id")
@GenericGenerator(name="id",strategy="assigned")
@Column(length=8)
private

@Column

  • @Column可将属性映射到列,使用该注解来覆盖默认值
  • @Column描述了数据库表中该字段的详细定义,这对于根据JPA注解生成数据库表结构的工具非常有用
  • 常用属性有如下几个
  • name:可选,表示数据库表中该字段名称,默认情形属性名称一致
  • nullable:可选,表示该字段是否允许为null,默认为true
  • unique:可选,表示该字段是否是唯一标识,默认为false
  • length:可选,表示该字段的大小,仅对String类型的字段有效,默认为255,如果是主键的话则不能使用默认值
  • insertable:可选,表示在ORM框架执行插入操作时,该字段是否应出现在INSERT语句中,默认为true
  • updateable:可选,表示在ORM框架执行更新操作时,该字段是否应出现在UPDATE语句中,默认为true,对于一经创建就不可以更改的字段,该属性非常有用,如注册日期

@Embedded

  • @Embedded是注释属性的,表示该属性的类是嵌入类
  • 同时嵌入类也必须标注@Embeddable注解

@EmbeddedId

  • @EmbeddedId使用嵌入式主键类实现复合主键
  • 注意:嵌入式主键类必须实现Serializable接口、必须有默认的public无参构造函数、必须覆盖equals()和hashCode()方法
import java.io.Serializable;
import javax.persistence.Embeddable;

@Embeddable
public class Address implements Serializable{

private static final long serialVersionUID = 1L;

private String address;

private String phone;

public Address() {
}

@Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}

@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
}


----------


另一个类中
@EmbeddedId
private

@Transient

  • 可选,表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性,如果一个属性并非数据库表的字段映射,就务必将其标注为@Transient,否则ORM框架默认其注解为@Basic

Hibernate关联映射注解

  • 一对一单向外键
  • 一对一双向外键
  • 一对一双向外键联合主键
  • 多对一单向外键
  • 一对多单向外键
  • 一对多双向外键
  • 多对多单向外键
  • 多对多双向外键

一对一单向外键

@OneToOne(cascade = CascadeType.ALL)//级联操作
@JoinColumn(name = "pid", unique = true)//唯一
  • 保存时应该先保存外键对象,再保存主表对象
  • 学生一对一身份证
package oneToOne;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

@Entity
public class Students

@Id
@GeneratedValue// 自增长
private int sid;

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "pid", unique = true)
private IdCard idCard;
}


----------


package oneToOne;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import org.hibernate.annotations.GenericGenerator;

@Entity
public class IdCard

@Id
@GeneratedValue(generator = "pid")
@GenericGenerator(name = "pid", strategy = "assigned")
@Column(length = 8)
private String pid;

private

一对一双向外键

  • 主控方的配置同一对一单向外键关联
  • 被控方:@OneToOne(mappedBy = “idCard”)
  • 双向关联,必须设置mappedBy属性。因为双向关联只能交给一方去控制,不可能在双方都设置外键保存关联关系,否则双方都无法保存
  • 学生类同上面一样
package oneToOne;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;

import org.hibernate.annotations.GenericGenerator;

@Entity
public class IdCard

@Id
@GeneratedValue(generator = "pid")
@GenericGenerator(name = "pid", strategy = "assigned")
@Column(length = 8)
private String pid;

private String sname;

@OneToOne(mappedBy = "idCard")
private

一对一双向外键联合主键

  1. 创建主键类,加@Embeddable
  2. 主键类必须实现Serializable接口,重写hashCode()和equals()方法
  3. 联合主键上使用@EmbeddedId

多对一单向外键

  • 多方持有一方的引用,比如:多个学生对应一个班级(多对一)
@ManyToOne(cascade = { CascadeType.ALL }, //级联操作
fetch =FetchType.EAGER)//抓取策略:积极
@JoinColumn(name = "cid",//外键属性名
referencedColumnName = "CID")//数据库表中字段名
package oneToMany;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Students

@Id
@GeneratedValue// 自增长
private int sid;

@ManyToOne(cascade = { CascadeType.ALL },
fetch = FetchType.EAGER)
@JoinColumn(name = "cid", referencedColumnName = "CID")
private ClassRoom classRoom;
}


----------


import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import org.hibernate.annotations.GenericGenerator;

@Entity
public class ClassRoom

@Id
@GeneratedValue(generator = "cid")
@GenericGenerator(name = "cid", strategy = "assigned")
@Column(length = 8)
private

一对多单向外键

  • 一方持有多方的集合,一个班级有多个学生(一对多)
@OneToMany(cascade = { CascadeType.ALL }, 
fetch = FetchType.LAZY)//懒加载
@JoinColumn(name = "cid")//外键属性名
students和上面的一样
package oneToMany;

import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;

import org.hibernate.annotations.GenericGenerator;

@Entity
public class ClassRoom

@Id
@GeneratedValue(generator = "cid")
@GenericGenerator(name = "cid", strategy = "assigned")
@Column(length = 8)
private String cid;

@OneToMany(cascade = { CascadeType.ALL },
fetch = FetchType.LAZY)
@JoinColumn(name = "cid")
private

总结:多对一的时候,多方设置EAGER,一方设置LAZY

多对多单向外键

  • 学生和教师构成多对多的关联关系
  • 其中一个多方持有另一个多方的集合对象(学生持有教师的集合)
@ManyToMany
@JoinTable(name = "teachers_students",
joinColumns = { @JoinColumn(name = "sid") },
inverseJoinColumns = { @JoinColumn(name = "tid") })
package manyToMany;

import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.hibernate.annotations.GenericGenerator;

@Entity
public class Teachers

@Id
@GeneratedValue(generator = "tid")
@GenericGenerator(name = "tid", strategy = "assigned")
@Column(length = 8)
private String tid;
}


----------
package manyToMany;

import java.util.Set;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;

public class Students

@Id
@GeneratedValue// 自增长
private int sid;

@ManyToMany
@JoinTable(name = "teachers_students",
joinColumns = { @JoinColumn(name = "sid") },
inverseJoinColumns = { @JoinColumn(name = "tid") })
private

多对多双向外键

  • 双方持有对方的集合对象,其中一方设置
@ManyToMany(mappedBy = "teachers")
package manyToMany;

import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.hibernate.annotations.GenericGenerator;

@Entity
public class Teachers

@Id
@GeneratedValue(generator = "tid")
@GenericGenerator(name = "tid", strategy = "assigned")
@Column(length = 8)
private String tid;

@ManyToMany(mappedBy = "teachers")
private