hibernate多对一双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接。
本系列将介绍Hibernate中主要的几种关联映射
Hibernate一对一主键单向关联
Hibernate一对一主键双向关联
Hibernate一对一外键单向关联
Hibernate一对一外键双向关联
Hibernate多对一单向关联
Hibernate多对一双向关联
Hibernate多对多关联
代码都写有注释,主要包括(核心配置文件,实体映射文件,实体类,测试类,数据库)主要操作有增删改查。
本篇主要介绍Hibernate多对一单向关联:
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 配置数据库连接驱动类 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 配置数据库连接字符串 --> <property name="connection.url"><![CDATA[jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8]]></property> <!-- 配置数据库连接用户名 --> <property name="connection.username">root</property> <!-- 配置数据库连接密码 --> <property name="connection.password">123456</property> <!-- 配置数据库方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 配置数据库表生成策略 --> <!--<property name="hibernate.hbm2ddl.auto">update</property> --> <!-- 配置是否打印显示SQL语句 --> <property name="show_sql">true</property> <!-- 配置是否格式化显示SQL语句 --> <property name="format_sql">true</property> <!-- 配置hibernate是否自动提交事务 --> <!--<property name="hibernate.connection.autocommit">true</property> --> <!-- 配置实体类对应的映射文件 --> <!-- 多对一双向关联配置 --> <mapping resource="com/great/entity/Class.hbm.xml"></mapping> <mapping resource="com/great/entity/Student.hbm.xml"></mapping> </session-factory> </hibernate-configuration>
Student.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping package="com.great.entity"> <!-- 配置实体类与数据库表的映射关系 --> <class name="Student" table="student"> <!-- 配置主键映射关系 --> <id name="id" column="sId" type="int"> <!-- 配置主键生成策略 --> <generator class="identity"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="sName" column="sName" type="string"></property> <!-- 多对一关联关系配置 --> <!-- many-to-one标签声明多对一关联关系,name指定多方所维护的一方的实例名 --> <many-to-one name="classes" class="com.great.entity.Class" cascade="save-update"> <!-- column标签指定关联外键,还是子表的外键列名 --> <column name="cId"></column> </many-to-one> </class> </hibernate-mapping>
Class.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.great.entity"> <class name="Class" table="class"> <!-- 配置主键映射关系 --> <id name="cId" column="cId" type="int"> <!-- 配置主键生成策略 --> <generator class="identity"> </generator> </id> <!-- 配置属性和表字段映射关系 --> <property name="cName" column="cName" type="string"></property> <!-- 一对多关联关系配置 --> <!-- inverse属性设置为true代表一的一方不在拥有关联关系的控制权,而把控制权交给多的一方 --> <!-- fetch属性用来指定子表数据的抓取策略,默认值为"select",代表对主表子表进行单独查询 ,对主表子表单独发select语句 --> <!-- fetch属性用来指定子表数据的抓取策略,设置为"join"时,代表对主表子表进行关联查询,对主表子表发出关联查询语句 --> <!-- lazy属性用来指定子表数据是否延迟加载,fetch="select"时起作用,fetch="join"时不起作用 --> <!-- fetch="select" lazy="true" --> <set name="students" cascade="all" inverse="true"> <!-- key配置的是子表的外键列名 --> <key column="cId"></key> <!-- one-to-many标签声明关联关系是一对多,class指定多方的实体类类型 --> <one-to-many class="com.great.entity.Student" /> </set> </class> </hibernate-mapping>
Student.java
package com.great.entity; import com.great.entity.Class; public class Student { private int id; private String sName; // 多对一映射时,因为要维护一的一方的实例,所以外键不需要映射 // private int cId; private Class classes; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getsName() { return sName; } public void setsName(String sName) { this.sName = sName; } public Class getClasses() { return classes; } public void setClasses(Class classes) { this.classes = classes; } }
Class.java
package com.great.entity; import java.util.HashSet; import java.util.Set; import com.great.entity.Student; public class Class { // 班级id private int cId; // 班级名字 private String cName; // 注意点:必须new一个Set的实现类的实例 // 原因:子表不一定有主表的关联数据,所以可能取出空集合,引发空指针异常 private Set<Student> students = new HashSet<Student>(); public int getcId() { return cId; } public void setcId(int cId) { this.cId = cId; } public String getcName() { return cName; } public void setcName(String cName) { this.cName = cName; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } @Override public String toString() { return "Class [cId=" + cId + ", cName=" + cName + ", students=" + students + "]"; } }
TestManyToOneBoth.java
package com.great.test; import java.util.Iterator; import java.util.Set; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.great.entity.Class; import com.great.entity.Student; public class TestManyToOneBoth { static Session session; // 多对一双向关联 @BeforeClass public static void setUpBeforeClass() throws Exception { // 加载hibernate主配置文件 Configuration cfg = new Configuration().configure(); // 构建session工厂 SessionFactory sf = cfg.buildSessionFactory(); // 打开session session = sf.openSession(); } @AfterClass public static void tearDownAfterClass() throws Exception { // 关闭session,释放资源 session.close(); } // select1, 通过class查询到student @Test public void testManyToOneBothSelect1() { Class c = (Class) session.get(Class.class, 5); System.out.println("班级为:" + c.getcName()); System.out.println("cId:" + c.getcId()); Set<Student> students = c.getStudents(); Iterator<Student> it = students.iterator(); while (it.hasNext()) { Student student = (Student) it.next(); System.out.println("学生姓名:" + student.getsName()); } } // select2, 通过student查询到class @Test public void testManyToOneBothSelect2() { Student s = (Student) session.get(Student.class, 3); System.out.println("学生名字为:" + s.getsName()); System.out.println("班级为:" + s.getClasses().getcName()); } // insert1,通过class保存数据,一条insert class.两条insert student @Test public void testManyToOneBothSave1() { Transaction ts = session.beginTransaction(); Class c = new Class(); c.setcName("通信2班"); Student s1 = new Student(); Student s2 = new Student(); s1.setsName("学员1"); s2.setsName("学员2"); c.getStudents().add(s1);// 必须加 c.getStudents().add(s2);// 必须加 s1.setClasses(c); s2.setClasses(c); session.save(c); ts.commit(); } // insert2,通过student保存数据,一条insert class.两条insert student @Test public void testManyToOneBothSave2() { Transaction ts = session.beginTransaction(); Class c = new Class(); c.setcName("硬件3班"); Student s1 = new Student(); Student s2 = new Student(); s1.setsName("学员3"); s2.setsName("学员4"); c.getStudents().add(s1);// 可加可不加 c.getStudents().add(s2);// 可加可不加 s1.setClasses(c); s2.setClasses(c); session.save(s1); session.save(s2); ts.commit(); } // delete1数据,仅仅删除student,cascade="save-update"[因为是多对一] 发出一条select ,一条delete @Test public void testManyToOneDelete1() { Transaction ts = session.beginTransaction(); Student student = (Student) session.get(Student.class, 17); session.delete(student); ts.commit(); } /* * delete2数据,通过删除class,把与class以及class相关的student全部删除,先删student,再删class,发出两条select * ,两条delete,在class配置文件中配置cascade="all" */ @Test public void testManyToOneDelete2() { Transaction ts = session.beginTransaction(); Class classes = (Class) session.get(Class.class, 2); session.delete(classes); ts.commit(); } // 更新数据1,通过student进行更新 @Test public void testManyToOneUpdate1() { Transaction ts = session.beginTransaction(); Student student = (Student) session.get(Student.class, 2); student.setsName("小哥"); student.getClasses().setcName("设计二班"); session.saveOrUpdate(student); ts.commit(); } // 更新数据2,通过class进行更新 @Test public void testOneToOneUpdate2() { Transaction ts = session.beginTransaction(); Class classes = (Class) session.get(Class.class, 11); classes.setcName("工业设计五班"); Set<Student> students = classes.getStudents(); Iterator<Student> it = students.iterator(); while (it.hasNext()) { Student student = (Student) it.next(); System.out.println("学生姓名:" + student.getsName()); if ("吴邪".equals(student.getsName())) { student.setsName("吴小邪"); } } ts.commit(); } }
数据库:
student表
三个字段 sId sName cId(外键)
class表
两个字段 cId cName
注意:在student表的cId上建立外键关系。
hibernate多对一双向关联的更多相关文章
- Java进阶知识12 Hibernate多对多双向关联(Annotation+XML实现)
1.Annotation 注解版 1.1.应用场景(Student-Teacher):当学生知道有哪些老师教,老师也知道自己教哪些学生时,可用双向关联 1.2.创建Teacher类和Student类 ...
- Hibernate多对多双向关联的配置
Hibernate的双向多对多关联有两种配置方法:那我们就来看看两种方案是如何配置的. 一.创建以各自类为类型的集合来关联 1.首先我们要在两个实体类(雇员<Emploee>.工程< ...
- Hibernate多对多双向关联
以Student和Course为例,一个学生可以选多门课程,一门课程也可以被多个学生选取: 持久化类Student: package bean; import java.util.Set; publi ...
- Hibernate多对多双向关联需要注意的问题(实例说话)
以Student和Course为例,一个学生可以选多门课程,一门课程也可以被多个学生选取: 持久化类Student: package bean; import java.util.Set; publi ...
- hibernate 多对多双向关联
package com.bjsxt.hibernate; import java.util.HashSet; import java.util.Set; import javax.persistenc ...
- Java进阶知识10 Hibernate一对多_多对一双向关联(Annotation+XML实现)
本文知识点(目录): 1.Annotation 注解版(只是测试建表) 2.XML版 的实现(只是测试建表) 3.附录(Annotation 注解版CRUD操作)[注解版有个问题:插入值时 ...
- hibernate多对一单向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- Java进阶知识11 Hibernate多对多单向关联(Annotation+XML实现)
1.Annotation 注解版 1.1.应用场景(Student-Teacher):当学生知道有哪些老师教,但是老师不知道自己教哪些学生时,可用单向关联 1.2.创建Teacher类和Student ...
- Java进阶知识08 Hibernate多对一单向关联(Annotation+XML实现)
1.Annotation 注解版 1.1.在多的一方加外键 1.2.创建Customer类和Order类 package com.shore.model; import javax.persisten ...
随机推荐
- 【.net 深呼吸】细说CodeDom(6):方法参数
本文老周就给大伙伴们介绍一下方法参数代码的生成. 在开始之前,先补充一下上一篇烂文的内容.在上一篇文章中,老周检讨了 MemberAttributes 枚举的用法,老周此前误以为该枚举不能进行按位操作 ...
- Tomcat shutdown执行后无法退出进程问题排查及解决
问题定位及排查 上周无意中调试程序在Linux上ps -ef|grep tomcat发现有许多tomcat的进程,当时因为没有影响系统运行就没当回事.而且我内心总觉得这可能是tomcat像nginx一 ...
- 关于如何提高Web服务端并发效率的异步编程技术
最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...
- ABP文档 - SignalR 集成
文档目录 本节内容: 简介 安装 服务端 客户端 连接确立 内置功能 通知 在线客户端 帕斯卡 vs 骆峰式 你的SignalR代码 简介 使用Abp.Web.SignalR nuget包,使基于应用 ...
- ASP.NET Core的路由[2]:路由系统的核心对象——Router
ASP.NET Core应用中的路由机制实现在RouterMiddleware中间件中,它的目的在于通过路由解析为请求找到一个匹配的处理器,同时将请求携带的数据以路由参数的形式解析出来供后续请求处理流 ...
- SVD奇异值分解的基本原理和运用
SVD奇异值分解: SVD是一种可靠的正交矩阵分解法.可以把A矩阵分解成U,∑,VT三个矩阵相乘的形式.(Svd(A)=[U*∑*VT],A不必是方阵,U,VT必定是正交阵,S是对角阵<以奇异值 ...
- Java中,异常的处理及抛出
首先我们需要知道什么是异常? 常通常指,你的代码可能在编译时没有错误,可是运行时会出现异常.比如常见的空指针异常.也可能是程序可能出现无法预料的异常,比如你要从一个文件读信息,可这个文件不存在,程序无 ...
- SharePoint 2016 必备组件离线安装介绍
前言 SharePoint 必备组件安装,一直以来都是SharePoint安装过程中的最大的坑,尤其是不能联网的服务器.博主在这里简单介绍一下离线安装过程,并附组件包下载以及安装命令,并且在windo ...
- Android中实现APP文本内容的分享发送与接收方法简述
谨记(指定选择器Intent.createChooser()) 开始今天的内容前,先闲聊一下: (1)突然有一天头脑风暴,对很多问题有了新的看法和见解,迫不及待的想要分享给大家,文档已经写好了,我需要 ...
- 使用CocosSharp制作一个游戏 - CocosSharp中文教程
注:本教程翻译自官方<Walkthrough - Building a game with CocosSharp>,官方教程有很多地方说的不够详细,或者代码不全,导致无法继续,本人在看了G ...