Hibernate使用注解配置持久化类和关联关系

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 +
                '}';
    }
}

<mapping class="com.pojo.Student"></mapping>
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<Student> students = new HashSet<>();

    public Teacher() {
    }

    public Teacher(String teaName, Set<Student> 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<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "teaId=" + teaId +
                ", teaName='" + teaName + '\'' +
                ", students=" + students +
                '}';
    }
}
<mapping class="com.pojo.Teacher"></mapping>
  • @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<Student> students = new HashSet<>();

    public Teacher() {
    }

    public Teacher(Integer teaId, String teaName, Set<Student> 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<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> 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<Subject> subjects = new HashSet<>();


    public Student() {
    }

    public Student(Integer stuId, String stuName, Set<Subject> 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<Subject> getSubjects() {
        return subjects;
    }

    public void setSubjects(Set<Subject> 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<Student> students = new HashSet<>();

    public Subject() {
    }

    public Subject(Integer subId, String subName, Set<Student> 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<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> 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类关联的属性名。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容