Hibernate提供注解来进行对象一一关系映射,他可以代替大量的hbm.xml文件,使得Hibernate程序的文件数量大大精简。使用注解,可以直接将映射信息定义在持久化类中,而无需编写对应的.*hbm.xml
配置持久化类的常用注解
- @Entity 将一个类声明为一个持久化类,默认所有属性都映射在数据表中
- @Table 为持久化类映射指定表(table),目录catalog 和schema的名称,默认值持久化类名,不带包名
- @Id 声明了持久化类的标识属性(相当于数据表的主键)
- @GeneratedValue 定义标识属性值的生成策略
- @UniqueConstraint 定义表的唯一约束
- @Lob 标识属性将被持久化为Blob或Clob属性
- @Column 将属性映射到数据库字段
- @Transient 指定可以忽略的属性,不用持久化到数据库
使用Hibernate注解,需要导入javax.persistence包,常用注解都存放在这个包,javax.persistence包是JPA ORM规范的组合部分,JPA 全称
Java Persistence API ,他是通过JDK5.0注解或XML描述对象一一关系表的映射关系,并将运行时对象持久化到数据库中。Hibernate提供对JPA的实现
package com.pojo;
import javax.persistence.*;
@Entity
@Table(name = "student",catalog = "project")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "stuId")
private Integer stuId;
@Column(name = "stuName")
private String stuName;
@Transient
private Teacher teacher;
public Student() {
}
public Student(String stuName, Teacher teacher) {
this.stuName = stuName;
this.teacher = teacher;
}
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"stuId=" + stuId +
", stuName='" + stuName + '\'' +
", teacher=" + teacher +
'}';
}
}
package com.pojo;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(catalog = "project", name = "teacher")
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "teaId")
private Integer teaId;
@Column(name = "teaName")
private String teaName;
@Transient
private Set students = new HashSet<>();
public Teacher() {
}
public Teacher(String teaName, Set students) {
this.teaName = teaName;
this.students = students;
}
public Integer getTeaId() {
return teaId;
}
public void setTeaId(Integer teaId) {
this.teaId = teaId;
}
public String getTeaName() {
return teaName;
}
public void setTeaName(String teaName) {
this.teaName = teaName;
}
public Set getStudents() {
return students;
}
public void setStudents(Set students) {
this.students = students;
}
@Override
public String toString() {
return "Teacher{" +
"teaId=" + teaId +
", teaName='" + teaName + '\'' +
", students=" + students +
'}';
}
}
- @Table 可以省略,省略时默认表名于持久化类名相同
- @GeneratedValue 指定了OID的生成策略,如果不使用此注解,默认OID由程序赋值相当于映射文件中指定assigned。JPA提供4种标准用法
(1)AUTO:根据不同的数据库选择不同的策略相当于映射文件中的native
(2)TABLE:使用表保存id值
(3)IDENTITY:使用数据库自动生成主键值(主要时自动增长型:MySQL,SQL Server)
(4)SEQUENCE:使用序列生成主键值(如Oracle),genertor="uuid"指定生成器是uuid - @SequenceGenerator设置了序列生成器,name="seq"定义了序列生成器名是seq;sequenceName="seq_id"指定了序列的名称seq_id;initialValue设置主键起始值;allocationSize设置了生成器分配id时的增量
- @Column 用于指定属性映射的数据库字段名,若不指定,则默认字段名和属性名相同
- @Transient用于忽略不需要持久化到数据库的属性,只是起到用于查询时封装查询数据
- @Entity 默认所有属性都会被映射到数据库表中的同名字段
使用注解定义的持久化类,在hibernate.cfg.xml的mapping元素中要使用class属性进行声明,以指定该持久化类的全类名
Hibernate注解配置关联关系
- @OneToOne 建立持久化类之间的一对一关联关系
- @OneToMany 建立持久化类之间一对多关联关系
- @ManyToOne建立持久化类之间多对一关联关系
- @ManyToMany建立持久化类之间多对多关联关系
注解开发双向一对多关联关系
package com.pojo;
import javax.persistence.*;
@Entity
@Table(name = "student", catalog = "project")
public class Student {
@Id
@Column(name = "stuId")
private Integer stuId;
@Column(name = "stuName")
private String stuName;
/**
* 一对多关联关系
* 延迟加载
* 关联外键
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "teaId")
private Teacher teacher;
public Student() {
}
public Student(Integer stuId, String stuName, Teacher teacher) {
this.stuId = stuId;
this.stuName = stuName;
this.teacher = teacher;
}
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"stuId=" + stuId +
", stuName='" + stuName + '\'' +
", teacher=" + teacher +
'}';
}
}
public class StudentDao extends BaseDao{
public void save(Student student)
{
this.getCurrentSession().save(student);
}
}
public class StudentBiz {
private StudentDao studentDao = new StudentDao();
public void save(Student student) {
Transaction tx = null;
try {
tx = studentDao.getCurrentSession().beginTransaction();
studentDao.save(student);
tx.commit();
} catch (HibernateException ex) {
ex.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
}
public class StudentTest {
private StudentBiz studentBiz=new StudentBiz();
@Test
public void save()
{
Student student=new Student();
student.setStuId(8);
student.setStuName("王八");
Teacher teacher=new Teacher();
teacher.setTeaId(1);
student.setTeacher(teacher);
studentBiz.save(student);
}
}
package com.pojo;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(catalog = "project", name = "teacher")
public class Teacher {
@Id
@Column(name = "teaId")
private Integer teaId;
@Column(name = "teaName")
private String teaName;
/**
* 一对多关联关系
* 延迟加载
* inverse="true" 值是Student类中与Teacher关联的属性名
* 级联cascade
*/
@OneToMany(fetch = FetchType.LAZY,mappedBy = "teacher",cascade = CascadeType.ALL)
private Set students = new HashSet<>();
public Teacher() {
}
public Teacher(Integer teaId, String teaName, Set students) {
this.teaId = teaId;
this.teaName = teaName;
this.students = students;
}
public Integer getTeaId() {
return teaId;
}
public void setTeaId(Integer teaId) {
this.teaId = teaId;
}
public String getTeaName() {
return teaName;
}
public void setTeaName(String teaName) {
this.teaName = teaName;
}
public Set getStudents() {
return students;
}
public void setStudents(Set students) {
this.students = students;
}
@Override
public String toString() {
return "Teacher{" +
"teaId=" + teaId +
", teaName='" + teaName + '\'' +
", students=" + students +
'}';
}
}
public class TeacherDao extends BaseDao {
public void save(Teacher teacher)
{
this.getCurrentSession().save(teacher);
}
}
public class TeacherBiz {
private TeacherDao teacherDao=new TeacherDao();
public void save(Teacher teacher)
{
Transaction tx=null;
try {
tx=teacherDao.getCurrentSession().beginTransaction();
teacherDao.save(teacher);
tx.commit();
}catch (HibernateException ex)
{
ex.printStackTrace();
if(tx!=null)
{
tx.rollback();
}
}
}
}
public class TeacherTest {
private TeacherBiz teacherBiz = new TeacherBiz();
@Test
public void save() {
Student s1 = new Student();
s1.setStuId(9);
s1.setStuName("柳九");
Student s2 = new Student();
s2.setStuId(10);
s2.setStuName("剑十");
Teacher teacher = new Teacher();
teacher.setTeaId(2);
teacher.setTeaName("王老");
teacher.getStudents().add(s1);
teacher.getStudents().add(s2);
s1.setTeacher(teacher);
s2.setTeacher(teacher);
teacherBiz.save(teacher);
}
}
使用@ManyToOne注解配置Student类和Teacher类之间的多对一关联。注解属性fetch=FetchType.Lazy设置多对一关联级别采用懒加载策略;若不指定,该属性的默认值是EAGER,查询Student将采用左外连接将相关Teacher对象一并查出。注解@JoinColumn(name="teaId")指定维护关系的外键字段是Student表中的teaId
使用@OneToMany配置Teacher类和Student类之间的一对多关系,属性mappedBy="teacher"将关联关系的控制权交给Student这一方,相当于配置文件的inverse="true"。mappedBy属性的值是Student类中与Teacher类关联的属性名。属性cascade={CascadeType.ALL}设置了级联操作的类型
- CascadeType.REMOVE :级联删除
- CascadeType.PERSIST :persist()方法级联
- CascadeType.MERGE :级联更新
- CascadeType.REFRESH :级联刷新
- CascadeType.ALL 包含所有级联操作
注解开发双向多对多关联关系
package com.pojo;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "student", catalog = "project")
public class Student {
@Id
@Column(name = "stuId")
private Integer stuId;
@Column(name = "stuName")
private String stuName;
@ManyToMany(mappedBy = "students", fetch = FetchType.LAZY)
private Set subjects = new HashSet<>();
public Student() {
}
public Student(Integer stuId, String stuName, Set subjects) {
this.stuId = stuId;
this.stuName = stuName;
this.subjects = subjects;
}
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public Set getSubjects() {
return subjects;
}
public void setSubjects(Set subjects) {
this.subjects = subjects;
}
@Override
public String toString() {
return "Student{" +
"stuId=" + stuId +
", stuName='" + stuName + '\'' +
", subjects=" + subjects +
'}';
}
}
package com.pojo;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "subject", catalog = "project")
public class Subject {
@Id
@Column(name = "subId")
private Integer subId;
@Column(name = "subName")
private String subName;
/**
* 多对多关联关系
* 懒加载
* 中间表
* 当前对象id在中间表的列名
* 关联的另一个表在中间表的列名
*/
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
@JoinTable(name = "sub_stu",//中间表名
joinColumns = {@JoinColumn(name = "sub_id", referencedColumnName = "subId")},//当前对象id在中间表的列名
inverseJoinColumns = {@JoinColumn(name = "stu_id", referencedColumnName = "stuId")}//关联的另一个表在中间表的列名
)
private Set students = new HashSet<>();
public Subject() {
}
public Subject(Integer subId, String subName, Set students) {
this.subId = subId;
this.subName = subName;
this.students = students;
}
public Integer getSubId() {
return subId;
}
public void setSubId(Integer subId) {
this.subId = subId;
}
public String getSubName() {
return subName;
}
public void setSubName(String subName) {
this.subName = subName;
}
public Set getStudents() {
return students;
}
public void setStudents(Set students) {
this.students = students;
}
@Override
public String toString() {
return "Subject{" +
"subId=" + subId +
", subName='" + subName + '\'' +
", students=" + students +
'}';
}
}
public class SubDao extends BaseDao{
public void save(Subject subject)
{
this.getCurrentSession().save(subject);
}
}
public class SubBiz {
private SubDao subDao=new SubDao();
public void save(Subject subject)
{
Transaction tx=null;
try {
tx=subDao.getCurrentSession().beginTransaction();
subDao.save(subject);
tx.commit();
}catch (HibernateException ex)
{
ex.printStackTrace();
if(tx!=null)
{
tx.rollback();
}
}
}
}
public class SubTest {
private SubBiz subBiz = new SubBiz();
@Test
public void save() {
Subject sub1 = new Subject();
sub1.setSubId(1);
sub1.setSubName("语文");
Subject sub2 = new Subject();
sub2.setSubId(2);
sub2.setSubName("数学");
Student stu1 = new Student();
stu1.setStuId(1);
stu1.setStuName("学生1");
Student stu2 = new Student();
stu2.setStuId(2);
stu2.setStuName("学生2");
sub1.getStudents().add(stu1);
sub1.getStudents().add(stu2);
sub2.getStudents().add(stu1);
sub2.getStudents().add(stu2);
stu1.getSubjects().add(sub1);
stu1.getSubjects().add(sub2);
stu2.getSubjects().add(sub1);
stu2.getSubjects().add(sub2);
subBiz.save(sub1);
subBiz.save(sub2);
}
}
Hibernate:
select
student_.stuId,
student_.stuName as stuName6_
from
project.student student_
where
student_.stuId=?
Hibernate:
select
student_.stuId,
student_.stuName as stuName6_
from
project.student student_
where
student_.stuId=?
Hibernate:
insert
into
project.subject
(subName, subId)
values
(?, ?)
Hibernate:
insert
into
project.student
(stuName, stuId)
values
(?, ?)
Hibernate:
insert
into
project.student
(stuName, stuId)
values
(?, ?)
Hibernate:
insert
into
sub_stu
(sub_id, stu_id)
values
(?, ?)
Hibernate:
insert
into
sub_stu
(sub_id, stu_id)
values
(?, ?)
Hibernate:
select
student_.stuId,
student_.stuName as stuName6_
from
project.student student_
where
student_.stuId=?
Hibernate:
select
student_.stuId,
student_.stuName as stuName6_
from
project.student student_
where
student_.stuId=?
Hibernate:
insert
into
project.subject
(subName, subId)
values
(?, ?)
Hibernate:
insert
into
sub_stu
(sub_id, stu_id)
values
(?, ?)
Hibernate:
insert
into
sub_stu
(sub_id, stu_id)
values
(?, ?)
使用@ManyToMany注解配置科目和学生的多对多关联关系fetch = FetchType.LAZY设置多对多关联级别采用延迟加载策略,属性cascade = {CascadeType.ALL}设置级联操作类型。
使用@JoinTable注解配置中间表关联Sub表和Stu表,属性name = "sub_stu"生成sub_stu中间表,属性joinColumns = {@JoinColumn(name = "sub_id", referencedColumnName = "subId")}生成当前对象id在中间表的列名,属性 inverseJoinColumns = {@JoinColumn(name = "stu_id", referencedColumnName = "stuId")}关联的另一个对象id在中间表的列名
使用@ManyToMany注解配置学生和科目的多对多关联关系,属性fetch = FetchType.LAZY设置多对多关联级别采用延迟加载策略,属性mappedBy = "students"将关联关系的控制权交给Subject这一方,相当于配置关系的inverse="true",mappedBy属性的值是Subject类中与Student类关联的属性名。