注意:我使用的是Hibernate5.2版本。
一、关联关系映射
单向关联:一对一、一对多、多对一。
使用连接表单向:一对一、一对多、多对一、多对多。
双向关联:一对一、一对多。
使用连接表的双向关联:一对一、一对多、多对多。
二、自动生成表
这里介绍一下Schema自动生成(Automatic schema generation)
可以从你的映射文件使用一个Hibernate工具生成DDL。 生成的schema包含有对实体和集合类表的完整性引用约束(主键和外键)。涉及到的标示符生成器所需的表和sequence也会同时生成。
在使用这个工具的时候,你必须 通过hibernate.dialet属性指定一个SQL方言(Dialet),因为DDL是与供应商高度相关的。
首先,要定制你的映射文件,来改善生成的schema。
注意:以前的版本生成方法不同请查看具体API
前提配置好classname.hbm.xml和hibernate.xml
public void testCreadDB(){
ServiceRegistry serviceRegistry=new StandardServiceRegistryBuilder().configure().build();
Metadata metadataImplementor=new MetadataSources(serviceRegistry).buildMetadata();
SchemaExport schemaExport=new SchemaExport();
schemaExport.create(EnumSet.of(TargetType.DATABASE), metadataImplementor);
}
三、单向一对多
Grade.java
package com.pojo;
import java.util.HashSet;
import java.util.Set;
import javassist.expr.NewArray;
public class Grade {
private int id;
private String name;
private Set<Student> students=new HashSet<Student>(0);
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
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;
}
}
Student.java
package com.pojo;
public class Student {
private int id;
private String name;
private int age;
//private Grade grade;
// private int gradeId;
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Grade.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pojo">
<class name="Grade" >
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<!-- set是grade中集合的属性 name属性名称-->
<set name="students" table="student">
<!-- key表示外键 colume外键列名 not-null外键不能空-->
<key column="grade_id" not-null="true"></key>
<!-- 一对多 -->
<one-to-many class="com.pojo.Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pojo">
<class name="Student" >
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<property name="age" />
</class>
</hibernate-mapping>
SessionFactoryUtil.java 单例创建sessionfactory
package com.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SessionFactoryUtil {
private static SessionFactory sessionfactory;
private SessionFactoryUtil(){
}
public static SessionFactory getSessionFactory(){
if(sessionfactory==null)
{
Configuration configuration=new Configuration();
configuration.configure();
sessionfactory=configuration.buildSessionFactory();
}
return sessionfactory;
}
}
测试代码:
package com.test;
import java.util.Iterator;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.pojo.Grade;
import com.pojo.Student;
import com.util.SessionFactoryUtil;
public class StudentDemo {
public static void main(String[] args) {
StudentDemo studentDemo = new StudentDemo();
studentDemo.oneTomany();
}
public void oneTomany() {
// 单向一对多
SessionFactory sessionFactory = SessionFactoryUtil.getSessionFactory();// 单例创建sessionfactory
Session session = sessionFactory.openSession();// 创建session对象
Transaction transaction = session.beginTransaction();// 开始事务
// 添加数据
Grade grade = new Grade();
grade.setName("基础部");
Student student = new Student();
student.setName("沈雪冰");
student.setAge(23);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(19);
// 关联,建立单向关系
grade.getStudents().add(student);
grade.getStudents().add(student2);
// 保存顺序根据外键来决定的,如果外键不能为null 那么先保存一的一端,否则随意保存
session.save(grade);
session.save(student);
session.save(student2);
transaction.commit(); // 提交事务
// 取数据
Grade gradetemp = session.get(Grade.class, 1);// 取出id为1的grade对象
System.out.println("gradeName=" + gradetemp.getName());
System.out.println("grade所对应的一对多数据为:");
Iterator<Student> iterator = gradetemp.getStudents().iterator(); // 通过gradetemp获取student集合
while (iterator.hasNext()) {
// 取出student集合信息
Student temp = iterator.next(); // 取到一个数据
System.out.println("name=" + temp.getName() + ",age=" + temp.getAge());
}
session.close(); // 关闭session
}
}
运行结果:
gradeName=基础部
grade所对应的一对多数据为:
name=沈雪冰,age=23
name=李四,age=19
四、单向多对一
Grade.java
package com.pojo;
public class Grade {
private int id;
private String name;
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;
}
}
Studnet.java
package com.pojo;
public class Student {
private int id;
private String name;
private int age;
private Grade grade;
// private int gradeId;
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
Grade.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pojo">
<class name="Grade" >
<id name="id">
<generator class="native" />
</id>
<property name="name" />
</class>
</hibernate-mapping>
Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pojo">
<class name="Student" >
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<property name="age" />
<!--
many-to-one属性:
* name:关联映射的(一那方的)属性名字。
* column:和一那方关联的表的外键。数据库字段
* class:name属性对应持久化类的全路径。
* not-null:是否允许为空。
-->
<many-to-one name="grade" class="Grade"
column="grade_id" not-null="true" foreign-key="FKgrade"
></many-to-one>
</class>
</hibernate-mapping>
测试代码:
package com.test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.pojo.Grade;
import com.pojo.Student;
import com.util.SessionFactoryUtil;
public class StudentDemo {
public static void main(String[] args) {
StudentDemo studentDemo=new StudentDemo();
studentDemo.manytoOne();
}
public void manytoOne(){
//单向多对一
SessionFactory sessionFactory=SessionFactoryUtil.getSessionFactory();//单例创建
Session session=sessionFactory.openSession();//创建一个session
Transaction transaction=session.beginTransaction();//开始事务
//添加数据
Grade grade=new Grade();
grade.setName("基础部");
Student student=new Student();
student.setName("沈雪冰");
student.setAge(23);
student.setGrade(grade);
Student student2=new Student();
student2.setName("李四");
student2.setAge(19);
student2.setGrade(grade);
Student student3=new Student();
student3.setName("王麻子");
student3.setAge(30);
student3.setGrade(grade);
//保存数据
session.save(grade);
session.save(student);
session.save(student2);
session.save(student3);
transaction.commit();//提交数据
session.close();//关闭数据
//取数据
Grade temp=new Grade();
Grade temp2=new Grade();
Grade temp3=new Grade();
System.out.println("多对一:");
System.out.println("每位学生所对应数据:");
temp=student.getGrade();//取出student对应的grade
System.out.println("name="+student.getName()+",age="+student.getAge()+",grade="+temp.getName());
temp2=student2.getGrade();//取出student3对应的grade
System.out.println("name="+student2.getName()+",age="+student2.getAge()+",grade="+temp2.getName());
temp3=student3.getGrade();//取出student3对应的grade
System.out.println("name="+student3.getName()+",age="+student3.getAge()+",grade="+temp3.getName());
}
}
运行结果:
多对一:
每位学生所对应数据:
name=沈雪冰,age=23,grade=基础部
name=李四,age=19,grade=基础部
name=王麻子,age=30,grade=基础部
五、双向一对多
Grade.java
package com.pojo;
import java.util.HashSet;
import java.util.Set;
import javassist.expr.NewArray;
public class Grade {
private int id;
private String name;
private Set<Student> students=new HashSet<Student>(0);
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
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;
}
}
Student.java
package com.pojo;
/**
***********************************
*
*@类名 Student
*@时间 2017年6月5日下午3:11:28
*@作者 沈雪冰
*@描述
*
***********************************
*/
public class Student {
private int id;
private String name;
private int age;
private Grade grade;
// private int gradeId;
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
Grade.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pojo">
<class name="Grade" >
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<!-- set是grade中集合的属性 name属性名称
-->
<set name="students" table="student" >
<!-- key表示外键 colume外键列名 not-null外键不能空-->
<key column="grade_id" not-null="true"></key>
<!-- 一对多 -->
<one-to-many class="com.pojo.Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.pojo">
<class name="Student" >
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<property name="age" />
</class>
</hibernate-mapping>
测试代码:
package com.test;
import java.util.Iterator;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.pojo.Grade;
import com.pojo.Student;
import com.util.SessionFactoryUtil;
public class StudentDemo {
public static void main(String[] args) {
StudentDemo studentDemo = new StudentDemo();
studentDemo.oneTomany();
}
public void oneTomany() {
// 双向一对多
SessionFactory sessionFactory = SessionFactoryUtil.getSessionFactory();// 单例创建sessionfactory
Session session = sessionFactory.openSession();// 创建session
Transaction transaction = session.beginTransaction();// 开始事务
Grade grade = new Grade();
grade.setName("基础部");
Student student = new Student();
student.setName("沈雪冰");
student.setAge(23);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(19);
// 建立双向关系
grade.getStudents().add(student);
grade.getStudents().add(student2);
student.setGrade(grade);
student2.setGrade(grade);
// 保存顺序根据外键来决定的,如果外键不能为null 那么先保存一的一端,否则随意保存
session.save(grade);
session.save(student);
session.save(student2);
transaction.commit(); // 提交事务
// 取数据
Grade gradetemp = session.get(Grade.class, 1); // 获取id为1grade对象
System.out.println("gradeName=" + grade.getName());
System.out.println("grade所对应的一对多数据为:");
Iterator<Student> iterator = gradetemp.getStudents().iterator();// 这里的学生信息是根据gradetemp信息获取的
while (iterator.hasNext()) {
Student temp = iterator.next(); // 取到一个数据
System.out.println("name=" + temp.getName() + ",age=" + temp.getAge() + "" + ",gradename="
+ temp.getGrade().getName());// 这里的grade信息是通过student信息获取的
}
session.close(); // 关闭session
}
}
运行结果:
要注意和上边单向一对多的区别
gradeName=基础部
grade所对应的一对多数据为:
name=沈雪冰,age=23,gradename=基础部
name=李四,age=19,gradename=基础部