本章主要是描述几种经典映射关系,顺带比较Hibernate4.x和Hibernate5.x之间的区别。

一、建立测试工程目录

有关实体类之间的相互映射关系,Hibernate官方文档其实描述的非常详细,这里只提供几种常见映射。(推荐4.3.11版本的 hibernate-release-4.3.11.Final\documentation\manual)

二、编写映射关系

(1)one2one单表内嵌映射:

package model.family;

import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; @Entity
public class Husband {
private int id;
private String husbandName;
private Wife wife; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getHusbandName() {
return husbandName;
} public void setHusbandName(String husbandName) {
this.husbandName = husbandName;
} // 两个实体对象共用一张数据表,提高查询速度
@Embedded
public Wife getWife() {
return wife;
} public void setWife(Wife wife) {
this.wife = wife;
} }

Husband.java

package model.family;

//不用添加任何注解,持久化过程通过主表完成
public class Wife {
private String wifeName; public String getWifeName() {
return wifeName;
} public void setWifeName(String wifeName) {
this.wifeName = wifeName;
}
}

Wife.java

(2)one2one外键映射:

package model.userinfo;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Transient; @Entity
public class User {
private int id;
private String username;
private String password;
private String confirm;
private Information info; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} /*
* 延迟加载,级联操作。
* 删除开启了级联的一方,被级联的一方也会被删除
* 注意:如果session的操作是通过hibernate控制,延迟加载不会出问题。如果是通过手工开启实物,操作不当延迟加载可能抛出懒加载异常
*/
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
public Information getInfo() {
return info;
} public void setInfo(Information info) {
this.info = info;
} // 本字段不参与持久化过程
@Transient
public String getConfirm() {
return confirm;
} public void setConfirm(String confirm) {
this.confirm = confirm;
}
}

User.java

package model.userinfo;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType; //注解也可以直接配置在字段上,但是不推荐。据说原因是可能破坏oop封装。但是我觉得有时这样配置可以让代码显得更加整洁,特别是在Spring中。
@Entity
public class Information {
@Id
@GeneratedValue
private int id;
@OneToOne
private User user;
@Temporal(TemporalType.DATE)
private Date resgisterDate;
private String address; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
} public Date getResgisterDate() {
return resgisterDate;
} public void setResgisterDate(Date resgisterDate) {
this.resgisterDate = resgisterDate;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} }

Information.java

(3)many2many多表映射:

场景描述:学校里有多个老师,每个老师教授多个学生,每个学生每一门课程会有一个得分。

 package model.school;

import java.util.HashSet;
import java.util.Set; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany; @Entity
public class Teacher {
private int id;
private String tchName;
private Set<Student> students = new HashSet<Student>(); @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getTchName() {
return tchName;
} public void setTchName(String tchName) {
this.tchName = tchName;
} //老师和学生的对应表由学生一方负责维护
@ManyToMany(mappedBy = "teachers")
public Set<Student> getStudents() {
return students;
} public void setStudents(Set<Student> students) {
this.students = students;
} }

Teacher.java

package model.school;

import java.util.HashSet;
import java.util.Set; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany; @Entity
public class Student {
private int id;
private String stuName;
private Set<Teacher> teachers = new HashSet<Teacher>();
private Set<Score> scores = new HashSet<Score>(); @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getStuName() {
return stuName;
} public void setStuName(String stuName) {
this.stuName = stuName;
} /*
* many2many必须使用中间表,配置中间表的表明和列名
*/
@ManyToMany
@JoinTable(name = "student_teacher", joinColumns = { @JoinColumn(name = "studentId") }, inverseJoinColumns = {
@JoinColumn(name = "teacherId") })
public Set<Teacher> getTeachers() {
return teachers;
} public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
} // 学生同分数之间的关系同样交给多的一方负责维护
@OneToMany(mappedBy = "student")
public Set<Score> getScores() {
return scores;
} public void setScores(Set<Score> scores) {
this.scores = scores;
} }

Student.java

package model.school;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne; @Entity
public class Score {
private int id;
private int courseScore;
private Teacher teacher;
private Student student; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public int getCourseScore() {
return courseScore;
} public void setCourseScore(int courseScore) {
this.courseScore = courseScore;
} @ManyToOne
public Teacher getTeacher() {
return teacher;
} public void setTeacher(Teacher teacher) {
this.teacher = teacher;
} @ManyToOne
public Student getStudent() {
return student;
} public void setStudent(Student student) {
this.student = student;
} }

Score.java

按照以上的映射关系生成数据表以后会注意到,其实老师和学生之间的关系表纯粹多余,分数表已经维护了双方的关系。重新优化他们之间的映射关系:

package model.school;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id; @Entity
public class Teacher {
private int id;
private String tchName; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getTchName() {
return tchName;
} public void setTchName(String tchName) {
this.tchName = tchName;
} }

Teacher.java

package model.school;

import java.util.HashSet;
import java.util.Set; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany; @Entity
public class Student {
private int id;
private String stuName;
private Set<Score> scores = new HashSet<Score>(); @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getStuName() {
return stuName;
} public void setStuName(String stuName) {
this.stuName = stuName;
} @OneToMany(mappedBy = "student")
public Set<Score> getScores() {
return scores;
} public void setScores(Set<Score> scores) {
this.scores = scores;
} }

Student.java

package model.school;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne; @Entity
public class Score {
private int id;
private int courseScore;
private Teacher teacher;
private Student student; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public int getCourseScore() {
return courseScore;
} public void setCourseScore(int courseScore) {
this.courseScore = courseScore;
} @ManyToOne
public Teacher getTeacher() {
return teacher;
} public void setTeacher(Teacher teacher) {
this.teacher = teacher;
} @ManyToOne
public Student getStudent() {
return student;
} public void setStudent(Student student) {
this.student = student;
} }

Score.java

由此可见,即使是一个相对复杂的映射关系也可以通过优化得到一个相对简单的数据模型。

(4)many2one和one2many单表树形映射:

场景描述:地图,一个国家包含多个省份,每个省份又包含多个城市...

package model.tree;

import java.util.HashSet;
import java.util.Set; import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table; @Entity
@Table(name = "_tree")
public class Tree {
private int id;
private String name;
private Tree parent;
private Set<Tree> children = new HashSet<Tree>(); @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} @Column(name = "t_name", unique = true)
public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @ManyToOne
public Tree getParent() {
return parent;
} public void setParent(Tree parent) {
this.parent = parent;
} //删除根节点,与它相关的所有子节点全部删除
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
public Set<Tree> getChildren() {
return children;
} public void setChildren(Set<Tree> children) {
this.children = children;
}
}

Tree.java

注意:以上4种映射关系在4.3.11版本中正常。但在5.0.6版本中id字段被系统强制指定为了@GeneratedValue(strategy=GenerationType.TABLE)的方式。我曾经尝试手工指定生成策略为auto或者identity均无效。如果是通过xml的方式配置是正常的,目前我还不清楚是什么原因导致的上述异常。这个问题造成了下面的映射关系目前只能在4.x版本中正常使用:

(5)one2one主键映射

package model.personaddr;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn; @Entity
public class Person {
private int id;
private String name;
private Address address; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} // 两张表通过主键关联
@OneToOne(optional = true)
@PrimaryKeyJoinColumn
public Address getAddress() {
return address;
} public void setAddress(Address address) {
this.address = address;
}
}

Person.java

package model.personaddr;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne; @Entity
public class Address {
private int id;
private String local;
private Person person; @Id
@GeneratedValue
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getLocal() {
return local;
} public void setLocal(String local) {
this.local = local;
} @OneToOne(mappedBy = "address")
public Person getPerson() {
return person;
} public void setPerson(Person person) {
this.person = person;
} }

Address.java

ps:好在主键映射在实际使用中并不常见。


最后按照惯例,提供整个项目的完整目录结构和IDE版本信息

Hibernate 基础配置及常用功能(二)的更多相关文章

  1. Hibernate 基础配置及常用功能(三)

    本章重点讲述Hibernate对象的三种状态以及如何配置二级缓存 有关Hibernate的三种状态如何相互转换网上都能查到,官方文档描述的也比较详细.这里主要是针对几个重点方法做代码演示. 一.状态转 ...

  2. Hibernate 基础配置及常用功能(一)

    本来是想等全部框架测试完以后再统一发布的,但是随着测试的一点点增加感觉把需要叙述的东西放在一起终将会是一场灾难.所以还是打算分成几章来描述,其中还包括一些有待解决的问题.短期很难腾出时间来仔细阅读Hi ...

  3. Hibernate学习笔记2.1(Hibernate基础配置)

    Hibernate基础配置 1.<property name="hbm2ddl.auto">update</property> 在SessionFactor ...

  4. Fedora 28 系统基础配置以及常用软件安装方式

    实验说明: 很多人说Linux很难用,很难上手,其实不然,倘若不玩游戏,其实很多发行版Linux都可以成为主力系统,就比如本章要讲的 Fedora 28.本章会从镜像来源.系统安装.基础配置和常用软件 ...

  5. JAVA基础语法:常用功能符以及循环结构和分支结构(转载)

    3.JAVA基础语法:常用功能符以及循环结构和分支结构 1.常用功能符 注释 ("文字"是被注释的部分) //文字 单行注释 /文字/ 多行注释 算术运算符 + - * / / 整 ...

  6. Ansible基础配置与常用模块使用

    环境介绍: Ansible服务端IP:192.168.2.215 Ansible客户端IP:192.168.2.216.192.168.2.218.192.168.2.113   一.创建Ansibl ...

  7. hibernate基础配置

    数据库表名和类名 一致 注解:可写可不写: XML:可写可不写: <class name="Student"> 不一致 注解:  public class Teache ...

  8. 3.Hibernate基础配置

    1.Hibernate.cfg.xml:hbm2ddl.auto 在SessionFactory创建时,自动检查数据库结构,或者将数据库schema的DDL导出到数据库 <property na ...

  9. Hibernate学习笔记2.3(Hibernate基础配置)

    映射,注释可以放在成员变量上面,也可以放在get方法上面 写在成员变量的话 破坏了java的面向对象思维 直接让hibernate访问内部的私有元素 要是能直接设指不合适哈哈 所以主张写在get方法上 ...

随机推荐

  1. O(n) 筛法求素数

    var tot,i,j,k,m,n:longint; prime:array[0..100000] of boolean; p:array[0..100000] of longint;begin re ...

  2. win 10 常见问题

    Microsoft Edge Can't Open Local Domains IE Edge浏览器打不开本地站点 解决方法:解决方法

  3. 实验五(简单嵌入式WEB服务器实验)问题总结

    实验五问题总结 问题链接:<信息安全系统设计基础>实验五实验报告 虽然将07_httpd文件中全部拷贝进了bc中,文件夹中拥有Makefile文件,但是还是无法通过make得到该文件夹中c ...

  4. require.js工作原理(初始)

    详情:请见阮一峰老师的日志:http://www.ruanyifeng.com/blog/2012/11/require_js.html: 导入:<script data-main=" ...

  5. vert.x学习(八),用JDBCClient配合c3p0操作数据库

    今天学习了下vert.x的JDBCClient,我这里将今天的学习笔记记录下来.这次学习中使用了c3p0. 用使用JDBCClient和c3p0得现在pom.xml文件里面导入对应的依赖,下面贴出xm ...

  6. HTTPS 进阶

    参考 一.中间人攻击 概念:攻击者插入到原本直接通信的双方,让双方以为还在直接跟对方通讯,但是实际上双方的通信对方已经变成中间人,信息已经被中间人获取或篡改. HTTPS 的攻击分为两类:SSL 连接 ...

  7. Glide请求图片能携带Cookie的哟!

    在Web编程中我们都很熟知一个概念,当有了seesion登录状态时,你可以访问一些资源但如果你没有登录的话很多资源是无法访问的. 在android的WebApi中当然一样拥有这个概念.比如,用户的头像 ...

  8. Windows zabbix监控远程进程实现机制

    最近负责zabbix监控部署方面的工作,需要完成本地服务端监控远程虚拟机的运行状态(CPU.打开的进程等),与大家分享下我的实现方法. (1) 首先,需要实现记录zabbix客户端的进程的批处理:za ...

  9. linux–nohup命令(转)

    在应用Unix/Linux时,我们一般想让某个程序在后台运行,于是我们将常会用 & 在程序结尾来让程序自动运行.比如我们要运行mysql在后台: /usr/local/mysql/bin/my ...

  10. vs2010/2013项目的C++所在文件夹越来越大如何解决?

    vs2010/2013项目所在文件夹越来越大如何解决? Tools->Options->Text Editor->C/C++->Advanced,在 Fallback Loca ...