Hibernate注解
原创
©著作权归作者所有:来自51CTO博客作者写代码的lorre的原创作品,请联系作者获取转载授权,否则将追究法律责任
使用注解的目的
为了简化繁琐的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属性级别注解
添加方式
@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
一对一双向外键联合主键
- 创建主键类,加@Embeddable
- 主键类必须实现Serializable接口,重写hashCode()和equals()方法
- 联合主键上使用@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