一对多测试案例

1、类图

2、创建表

drop table if exists t_student ;

drop table if exists t_class ;

create table t_class (
id int(5) primary key ,
name varchar(150)
) ; create table t_student (
id int(10) primary key ,
name varchar(150) ,
class_id int(5) ,
foreign key ( class_id ) references t_class( id )
) ; insert into t_class ( id , name ) values ( 1 , '计算机一班' );
insert into t_class ( id , name ) values ( 2 , '计算机二班' );
insert into t_class ( id , name ) values ( 3 , '网络一班' );
insert into t_class ( id , name ) values ( 4 , '网络二班' ); insert into t_student ( id , name , class_id ) values ( 1 , '张翠山' , 2);
insert into t_student ( id , name , class_id ) values ( 2 , '曾阿牛' , 2 );
insert into t_student ( id , name , class_id ) values ( 3 , '赵敏' , 1 );
insert into t_student ( id , name , class_id ) values ( 4 , '小昭' , 3 );

3、持久化类

班级类:

package ecut.onetomany.entity;

import java.io.Serializable;
import java.util.Set; public class Clazz implements Serializable { private static final long serialVersionUID = 235617966763001653L; private Integer id;
private String name; // 当前的班级都有那些学生
private Set<Student> students; // 维护从 班级( one ) 到 学生( many ) 的 一对多 关联关系 public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Set<Student> getStudents() {
return students;
} public void setStudents(Set<Student> students) {
this.students = students;
} }

班级类中使用students来使班级和学生相关联

学生类:

package ecut.onetomany.entity;

import java.io.Serializable;

public class Student  implements Serializable {

    private static final long serialVersionUID = 399214402506858645L;

    private Integer id;
private String name; public Student() {
super();
} public Student(String name) {
super();
this.name = name;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

4、映射文件

班级映射文件:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="ecut.onetomany.entity.Clazz" table="t_class"> <id name="id" type="integer" column="id" >
<generator class="increment" />
</id> <property name="name" type="string" column="name" /> <!-- 使用 set 标记 映射 Set 集合 , name 属性指定 实体类中的 Set 集合的名称,order-by 所对应的表中的列名 -->
<set name="students" order-by="id ASC" cascade="all" >
<!-- 使用 key 的 column 属性指定 对方 ( many 一方 ) 表中 参照 当前表 ( t_class ) 的主键的那个外键的名称 -->
<key column="class_id" />
<!-- 指定 对方 ( many 一方 ) 的类型 ( Set 集合中存放的元素的类型 ) -->
<one-to-many class="ecut.onetomany.entity.Student" />
</set> </class> </hibernate-mapping>

学生映射文件:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="ecut.onetomany.entity.Student" table="t_student"> <id name="id" type="integer" column="id" >
<generator class="increment" />
</id> <property name="name" type="string" column="name" /> </class> </hibernate-mapping>

5、hibernate配置文件

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 指定连接数据库的基本信息 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property> <!-- 设置事务隔离级别 , 取值可以是 1、2、4、8 -->
<property name="hibernate.connection.isolation">1</property>
<!-- 设置事务是否自动提交 , 取值可以是 true 、false -->
<property name="hibernate.connection.autocommit">false</property> <!-- 指定数据方言类 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 指示是否显示 执行过的 SQL 语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 指示是否对 SQL 语句进行格式化输出 -->
<property name="hibernate.format_sql">false</property> <mapping resource="ecut/onetomany/entity/Clazz.hbm.xml"/>
<mapping resource="ecut/onetomany/entity/Student.hbm.xml"/> </session-factory> </hibernate-configuration>

6、测试类

从数据库中获取一个班级对象,之后获得所属学生的集合:

package ecut.onetomany.test;

import java.util.HashSet;
import java.util.Set; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.onetomany.entity.Clazz;
import ecut.onetomany.entity.Student; public class TestOneToMany {
private SessionFactory factory ;
private Session session ; public @Before void init() {
// 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
Configuration config = new Configuration();
// 读取配置文件
config.configure("ecut/onetomany/hibernate.cfg.xml");
//config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件 // 使用 Configuration 创建 SessionFactory
factory = config.buildSessionFactory(); // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
session = factory.openSession();
} public @Test void loadClazz(){ Clazz c = session.find( Clazz.class , 2 ); if( c == null ){
System.out.println( "没有找到对应的班级" );
} else {
System.out.println( c.getId() + " : " + c.getName() ); Set<Student> students = c.getStudents(); // <set name="students" order-by="id DESC" > System.out.println( students.getClass() ); if( students == null || students.isEmpty() ) {
System.out.println( c.getName() + "还没有学生");
} else {
for( Student s : students ){
System.out.println( "\t" + s.getId() + " : " + s.getName() );
}
} } }public @After void destory(){
session.close();
factory.close();
} }

班级持久化类中的set是PersistentSet类其中可以排序,可以在班级映射文件中的set标签中指定order-by属性来给学生排序。

    <!-- 使用 set 标记 映射 Set 集合 , name 属性指定 实体类中的 Set 集合的名称,order-by 所对应的表中的列名 -->
<set name="students" order-by="id ASC" cascade="all" >

保存一个新创建的班级对象到数据库,并为其添加学生,将学生一起保存:

package ecut.onetomany.test;

import java.util.HashSet;
import java.util.Set; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.onetomany.entity.Clazz;
import ecut.onetomany.entity.Student; public class TestOneToMany {
private SessionFactory factory ;
private Session session ; public @Before void init() {
// 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
Configuration config = new Configuration();
// 读取配置文件
config.configure("ecut/onetomany/hibernate.cfg.xml");
//config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件 // 使用 Configuration 创建 SessionFactory
factory = config.buildSessionFactory(); // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
session = factory.openSession();
}
public @Test void saveClazz(){ Clazz c = new Clazz();
c.setName( "华山派" ); Set<Student> students = new HashSet<>(); Student s1 = new Student( "令狐冲" ) ;
students.add( s1 ); Student s2 = new Student( "岳灵珊" ) ;
students.add( s2 ); Student s3 = new Student( "陆大有" ) ;
students.add( s3 ); Student s4 = new Student( "林平之" ) ;
students.add( s4 ); c.setStudents( students ); // 确定 班级中都有哪些 学生 session.getTransaction().begin();
session.save( c ); // <set name="students" cascade="all" >
session.getTransaction().commit(); } public @After void destory(){
session.close();
factory.close();
} }

运行结果:

Hibernate: select max(id) from t_class
Hibernate: select max(id) from t_student
Hibernate: insert into t_class (name, id) values (?, ?)
Hibernate: insert into t_student (name, id) values (?, ?)
Hibernate: insert into t_student (name, id) values (?, ?)
Hibernate: insert into t_student (name, id) values (?, ?)
Hibernate: insert into t_student (name, id) values (?, ?)
Hibernate: update t_student set class_id=? where id=?
Hibernate: update t_student set class_id=? where id=?
Hibernate: update t_student set class_id=? where id=?
Hibernate: update t_sent set class_id=? where id=?

是先保存class然后再保存student,并通过update语句来指定班级号。

若没有在映射文件中的set标签指定cascade属性则会抛出java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance beforeQuery flushing:的异常,为了解决这个异常,可以在保存class前先保存一下student,或者是通过指定cascade属性来完成级联保存class的对象同时会把关联的瞬时状态的对象student也保存。

    <!-- 使用 set 标记 映射 Set 集合 , name 属性指定 实体类中的 Set 集合的名称,order-by 所对应的表中的列名 -->
<set name="students" order-by="id ASC" cascade="all" >

转载请于明显处标明出处:

https://www.cnblogs.com/AmyZheng/p/9317570.html

Hibernate学习(四)的更多相关文章

  1. hibernate学习四(关系映射一对一与组件映射)

    一.关系映射简介 在数据库中,表与表的关系,仅有外键.但使用hibernate后,为面向对象的编程,对象与对象的关系多样化:如 一对一,一对多,多对多,并具有单向和双向之分. 开始练习前,复制上一次项 ...

  2. --------------Hibernate学习(四) 多对一映射 和 一对多映射

    现实中有很多场景需要用到多对一或者一对多,比如上面这两个类图所展现出来的,一般情况下,一个部门会有多名员工,一名员工只在一个部门任职. 多对一关联映射 在上面的场景中,对于Employee来说,它跟D ...

  3. Hibernate学习四----------Blob

    © 版权声明:本文为博主原创文章,转载请注明出处 实例 1.项目结构 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

  4. hibernate学习四 hibernate关联关系映射

    在Hibernate中对象之间的关联关系表现为数据库中表于表之间的关系(表之间通过外键关联). 1 单向的一对一 主键关联  外键关联 2 单向的一对多 3 单向的多对一 4 单向的多对多 5 双向的 ...

  5. Hibernate学习之——搭建log4j日志环境

    昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...

  6. SSH框架之hibernate《四》

    hibernate第四天     一.JPA相关概念         1.1JPA概述             全称是:Java Persistence API.是sun公司推出的一套基于ORM的规范 ...

  7. Hibernate学习一:Hibernate注解CascadeType

    http://zy19982004.iteye.com/blog/1721846 ———————————————————————————————————————————————————————— Hi ...

  8. Hibernate学习---缓存机制

    前言:这些天学习效率比较慢,可能是手头的事情比较多,所以学习进度比较慢. 在之前的Hibernate学习中,我们无论是CURD,对单表查询还是检索优化,我们好像都离不开session,session我 ...

  9. (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合

    http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...

  10. >hibernate的四种状态

    hibernate的四种状态 1.临时状态 与数据库中没有相对应的数据,也不在session的管理之中,一般是新new出来的对象 2.持久化状态 对象在session的管理中,最后会在事务提交后,在数 ...

随机推荐

  1. 959F - Mahmoud and Ehab and yet another xor task xor+dp(递推形)+离线

    959F - Mahmoud and Ehab and yet another xor task xor+dp+离线 题意 给出 n个值和q个询问,询问l,x,表示前l个数字子序列的异或和为x的子序列 ...

  2. Lowest Common Multiple Plus 题解

    求n个数的最小公倍数. Input输入包含多个测试实例,每个测试实例的开始是一个正整数n,然后是n个正整数. Output为每组测试数据输出它们的最小公倍数,每个测试实例的输出占一行.你可以假设最后的 ...

  3. vue项目中解决跨域问题axios和

    项目如果是用脚手架搭建的(vue cli)项目配置文件里有个proxyTable proxyTable是vue-cli搭建webpack脚手架中的一个微型代理服务器,配置如下 配置和安装axios 安 ...

  4. python开发基础04-函数、递归、匿名函数、高阶函数、装饰器

    匿名函数 lamba lambda x,y,z=1:x+y+z 匿名就是没有名字 def func(x,y,z=1): return x+y+z 匿名 lambda x,y,z=1:x+y+z #与函 ...

  5. 第十一篇 深入Python的dict和set(二)

  6. Catalyst9K设备介绍

    Catalyst9K系列的里面包含了多款交换机,以及无线控制器,甚至包含了无线AP,如下将简单的介绍这几款产品的情况: 首先,这是一种总体的对应关系: 1.Catalyst9200 Series 主要 ...

  7. 洛谷P1130红牌(简单DP)

    题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌.获得红牌的过程是相当复杂 ,一共包括NNN个步骤.每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件.为了加快进程,每一步政府都 ...

  8. 【C语言】创建一个函数,利用该函数将两个字符串连接起来

    代码: #include<stdio.h> ], ]) { int i, j; ; c[i] != '\0'; i++); ; d[j] != '\0'; j++) { c[i++] = ...

  9. Could not initialize class net.sourceforge.tess4j.TessAPI 解决方法

    java.lang.NoClassDefFoundError: Could not initialize classnet.sourceforge.tess4j.TessAPI 主要原因是在Windo ...

  10. js相关--浅拷贝和深拷贝

    1.js的数据类型 基本概述:js的数据类型分为两种,分别为基本数据类型和引用数据类型,它们俩的区别在于基本数据类型采用值传递,引用数据类型采用指针形式传递. 如下所示:引用类型通过简单的=进行复制, ...