慕课网Hibernate初探之一对多映射实验及总结
一、本课核心
* 1、如何在MyEclipse中使用Hibernate
* 2、如何实现Hibernate中一对多的映射
* 3、如何创建Session对象
* 4、Hibernate如何使用增删改查
1、如何在MyEclipse中使用Hibernate
* Hibernat框架创建
* MyEclipse2016 CI 7版本
* Hibernate release-5.2.10.Final
* 方法一:自动创建
* 1、新建一个Java项目
* 2、右击项目,选择myeclipse,选择hibernate支持Project Facets[Capabilities]
* 3、然后点下一步就给你创建好了
*
* 方法二:手动创建
* 1、将需要的hibernate包以及MySql的jdbc添加并创建好路径(hibernate中lib中的required文件夹中的所有包)
* 2、在hebernate解压缩包下进行检索cfg.xml,找到配置文件
* 3、修改配置文件
* 4、在MyEclipse中创建sql文件
* 5、创建持久化类,也就是对应的实体类
* 6、创建映射文件,也可以在hebernate解压缩包下进行检索hbm.xml,拷到实体包下
2、如何实现Hibernate中一对多的映射
1 //在一方(班级)去定义一个多方(学生)的集合来表示一对多的关系 2 //set集合元素不能重复 3 private Set<Student> students = new HashSet<Student>(); 4 /* 5 * 总结: 6 * 一对多映射的核心: 7 * 通过在grade中添加student的集合来实现 8 * 1、grade里面的这个集合类,需要映射的时候给这个类里面加学生 9 * 2、grade这个类对应的映射文件中的 10 * <!-- 配置单向的一对多关联关系 --> 11 <set name="students" table="students"> 12 <!-- 指定关联的外键列 --> 13 <key > 14 <column name="gid"></column> 15 </key> 16 <!-- 指定一对多的类名 --> 17 <one-to-many class="com.imooc.entity.Student" /> 18 </set> 19 */
3、如何创建Session对象
* 创建会话,四步:
* 1、建立配置文件对象,处理我们写的那些配置文件,包括数据库配置文件和映射文件
* 2、开启Hibernate服务,就像我们生活中用什么东西要开启什么样的服务一样,而且要注册
* 3、创建会话工厂
* 4、创建会话
1 //创建配置对象 2 Configuration config = new Configuration().configure(); 3 //创建服务注册对象 4 ServiceRegistry serviceRegistry = new 5 StandardServiceRegistryBuilder().applySettings(config.getProperties()).configure().build();//这里有点不一样 6 //创建会话工厂对象 7 sessionFactory = config.buildSessionFactory(serviceRegistry); 8 session = sessionFactory.openSession();
4、Hibernate如何使用增删改查
Session使用:save():(增) delete():(删) update():(改) get()/load():(查)
二、实例代码
1、数据库配置文件:hibernate.cfg.xml
1 <!-- 2 ~ Hibernate, Relational Persistence for Idiomatic Java 3 ~ 4 ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later. 5 ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. 6 --> 7 <!DOCTYPE hibernate-configuration PUBLIC 8 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 9 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 10 11 <hibernate-configuration> 12 <session-factory> 13 <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> 14 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 15 <property name="hibernate.connection.username">root</property> 16 <property name="hibernate.connection.password">1314</property> 17 <property name="hibernate.connection.url"> 18 <![CDATA[ 19 jdbc:mysql://localhost:3306/Hibernate2?useUnicode=true&characterEncoding=utf8 20 ]]> 21 </property> 22 23 <property name="show_sql">true</property> 24 <property name="hbm2ddl.auto">update</property> 25 26 <!-- 指定映射文件的路径 --> 27 <mapping resource="Grade.hbm.xml" /> 28 <mapping resource="Student.hbm.xml" /> 29 30 31 </session-factory> 32 </hibernate-configuration>
2、实体类一Student.java
1 package com.imooc.entity; 2 3 import java.io.Serializable; 4 5 public class Student implements Serializable { 6 private int sid; //学生id 7 private String sname; //学生姓名 8 private String sex; //性别 9 10 //构造函数 11 12 public Student() { 13 super(); 14 } 15 16 17 public Student(String sname, String sex) { 18 super(); 19 this.sname = sname; 20 this.sex = sex; 21 } 22 23 24 public int getSid() { 25 return sid; 26 } 27 28 public void setSid(int sid) { 29 this.sid = sid; 30 } 31 public String getSname() { 32 return sname; 33 } 34 public void setSname(String sname) { 35 this.sname = sname; 36 } 37 public String getSex() { 38 return sex; 39 } 40 public void setSex(String sex) { 41 this.sex = sex; 42 } 43 44 45 }
3、Student类对应的映射文件 Student.hbm.xml
1 <?xml version="1.0"?> 2 3 <!DOCTYPE hibernate-mapping PUBLIC 4 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 5 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 6 7 <!-- 配置的是学生到班级的单向的一对多 --> 8 <hibernate-mapping> 9 <class name="com.imooc.entity.Student" table="student"> 10 <!-- name是类名,table是那么对应的类对应的数据库中的表名 --> 11 <!-- id是主键 --> 12 <id name="sid" type="java.lang.Integer"> 13 <column name="sid"></column> 14 <generator class="increment"></generator> 15 <!-- generator是主键生成策略 increment查找主键最大值,并且在最大值的基础上加1 --> 16 </id> 17 <property name="sname" type="java.lang.String"> 18 <column name="sname" length="20" not-null="true"></column> 19 </property> 20 <property name="sex"> 21 <column name="sex"></column> 22 </property> 23 24 </class> 25 26 </hibernate-mapping>
4、班级实体类 Grade.java
1 package com.imooc.entity; 2 3 import java.io.Serializable; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 //班级类 8 //添加集合表示一对多的关系 9 public class Grade implements Serializable { 10 private int gid; //班级id 11 private String gname; //班级名 12 private String gdesc; //班级描述 13 14 //在一方(班级)去定义一个多方(学生)的集合来表示一对多的关系 15 //set集合元素不能重复 16 private Set<Student> students = new HashSet<Student>(); 17 /* 18 * 总结: 19 * 一对多映射的核心: 20 * 通过在grade中添加student的集合来实现 21 * 1、grade里面的这个集合类,需要映射的时候给这个类里面加学生 22 * 2、grade这个类对应的映射文件中的 23 * <!-- 配置单向的一对多关联关系 --> 24 <set name="students" table="students"> 25 <!-- 指定关联的外键列 --> 26 <key > 27 <column name="gid"></column> 28 </key> 29 <!-- 指定一对多的类名 --> 30 <one-to-many class="com.imooc.entity.Student" /> 31 </set> 32 */ 33 34 //构造方法 35 public Grade(int gid, String gname, String gdesc, Set<Student> students) { 36 super(); 37 this.gid = gid; 38 this.gname = gname; 39 this.gdesc = gdesc; 40 this.students = students; 41 } 42 43 44 public Grade(String gname, String gdesc) { 45 super(); 46 this.gname = gname; 47 this.gdesc = gdesc; 48 } 49 50 51 public Grade() { 52 super(); 53 } 54 55 56 57 58 public int getGid() { 59 return gid; 60 } 61 62 63 64 public void setGid(int gid) { 65 this.gid = gid; 66 } 67 68 public String getGname() { 69 return gname; 70 } 71 72 public void setGname(String gname) { 73 this.gname = gname; 74 } 75 76 public String getGdesc() { 77 return gdesc; 78 } 79 80 public void setGdesc(String gdesc) { 81 this.gdesc = gdesc; 82 } 83 84 public Set<Student> getStudents() { 85 return students; 86 } 87 88 public void setStudents(Set<Student> students) { 89 this.students = students; 90 } 91 92 93 }
5、班级实体类对应的映射文件 Grade.hbm.xml
1 <?xml version="1.0"?> 2 3 <!DOCTYPE hibernate-mapping PUBLIC 4 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 5 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 6 7 <hibernate-mapping> 8 9 <class name="com.imooc.entity.Grade" table="grade"> 10 <!-- name是类名,table是那么对应的类对应的数据库中的表名 --> 11 <!-- id是主键 --> 12 <id name="gid" type="java.lang.Integer"> 13 <column name="gid"></column> 14 <generator class="increment"></generator> 15 <!-- generator是主键生成策略 increment查找主键最大值,并且在最大值的基础上加1 --> 16 </id> 17 <property name="gname" type="java.lang.String"> 18 <column name="gname" length="20" not-null="true"></column> 19 </property> 20 <property name="gdesc"> 21 <column name="gdesc"></column> 22 </property> 23 <!-- 配置单向的一对多关联关系 --> 24 <set name="students" table="students"> 25 <!-- 指定关联的外键列 --> 26 <key > 27 <column name="gid"></column> 28 </key> 29 <!-- 指定一对多的类名 --> 30 <one-to-many class="com.imooc.entity.Student" /> 31 </set> 32 33 </class> 34 35 </hibernate-mapping>
6、获取session的工具类:HibernateUtil.java
1 package com.imooc.util; 2 3 /* 4 * 总结: 5 * 创建会话,四步: 6 * 1、建立配置文件对象,处理我们写的那些配置文件,包括数据库配置文件和映射文件 7 * 2、开启Hibernate服务,就像我们生活中用什么东西要开启什么样的服务一样,而且要注册 8 * 3、创建会话工厂 9 * 4、创建会话 10 */ 11 import org.hibernate.Session; 12 import org.hibernate.SessionFactory; 13 import org.hibernate.boot.registry.StandardServiceRegistry; 14 import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 15 import org.hibernate.cfg.Configuration; 16 import org.hibernate.service.ServiceRegistry; 17 18 //工具类,用来进行会话的获取和关闭 19 public class HibernateUtil { 20 private static SessionFactory sessionFactory; 21 private static Session session; 22 23 //通过静态代码块来加载 24 static{ 25 //创建Configuration对象,读取hibernate.cfg.xml文件,完成初始化 26 // Configuration config = new Configuration().configure(); 27 // StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder(). 28 // applySettings(config.getProperties()); 29 // StandardServiceRegistry ssr = ssrb.build(); 30 // sessionFactory=config.buildSessionFactory(ssr); 31 //创建配置对象 32 Configuration config = new Configuration().configure(); 33 //创建服务注册对象 34 ServiceRegistry serviceRegistry = new 35 StandardServiceRegistryBuilder().applySettings(config.getProperties()).configure().build();//这里有点不一样 36 //创建会话工厂对象 37 sessionFactory = config.buildSessionFactory(serviceRegistry); 38 39 /* 40 * 总结: 41 * 创建会话,四步: 42 * 1、建立配置文件对象,处理我们写的那些配置文件,包括数据库配置文件和映射文件 43 * 2、开启Hibernate服务,就像我们生活中用什么东西要开启什么样的服务一样,而且要注册 44 * 3、创建会话工厂 45 * 4、创建会话 46 */ 47 } 48 49 //获取sessionFactory 50 public static SessionFactory getSessionFactory(){ 51 return sessionFactory; 52 } 53 54 //获取Session 55 public static Session getSession(){ 56 session = sessionFactory.openSession(); 57 return session; 58 } 59 60 //关闭Session 61 public static void closeSession(Session session){ 62 if (session!=null) { 63 session.close(); 64 } 65 } 66 67 }
7、测试功能类,测试增删改查:Test.java
1 /* 2 * 一定要主要总结啊,要把学到的东西变成自己的东西 3 * 其实Hibernate说难也难,说简单也简单,两步: 4 * 1、成功获取Session对象的环境搭建 5 * 2、Session使用:save():(增) delete():(删) update():(改) get()/load():(查) 6 * 7 * 这一次课的核心: 8 * 1、如何在MyEclipse中使用Hibernate 9 * 2、如何实现Hibernate中一对多的映射 10 * 3、如何创建Session对象 11 * 4、如何使用增删改查 12 * 13 */ 14 package com.imooc.entity; 15 /* 16 * 错误一: 17 * 出现错误:Dialect不对 18 * 解决方法:把配置文件方言改成org.hibernate.dialect.MySQL5InnoDBDialect就好 19 * 错误二: 20 * 出现错误:org.hibernate.MappingException: Unknown entity: com.imooc.entity.Grade 21 * 错误分析:映射文件错误,根本就没有成功读取Grade的映射文件 22 * 将配置文件中的添加实体映射删掉,报的错误一样,说明错误是这里或之前 23 * 修改这之前的,出现新的错误,说明错误就在这里 24 * 既然是报错找不到com.imooc.entity.Grade,我把所有出现这个的地方都改下,查到底是那里错句 25 * 错误提示session.save(g);这一句是错的,注释掉之后出现没有学生实体类的错误 26 * 说明两个映射文件根本都没有加进去 27 * com.imooc.entity.Grade这个包名是我在test里面引包,其实就是session没有找到Grade实体 28 * 待会去用eclipse试一下 29 * 解决方法:还是生产session会话那里有问题,用之前的eclipse里面hibernate生成会话的方式就解决了 30 * 还是因为hibernate的版本和他的版本不一样,用的hibernate里面的required也不一样 31 * 解决心得:其实这种看视频,真的要用的软件、包、工具和他一模一样才好 32 * 仔细分析,找错还是挺好找的 33 */ 34 35 36 import java.util.Set; 37 38 import org.hibernate.Hibernate; 39 import org.hibernate.Session; 40 import org.hibernate.Transaction; 41 42 import com.imooc.util.HibernateUtil; 43 44 /* 45 * 单向一对多关系 46 * (班级--->学生) 47 * 建立关联关系后,可以方便的从一个对象导航到另一个对象 48 * 注意关联的关系 49 */ 50 public class Test { 51 public static void main(String[] args){ 52 //add(); 53 //findStudentsByGrade(); 54 //update(); 55 delete(); 56 } 57 58 //将学生添加到班级 59 /* 60 * 方法测试对应的输出结果: 61 * 62 Hibernate: select max(gid) from grade 63 Hibernate: select max(sid) from student 64 Hibernate: insert into grade (gname, gdesc, gid) values (?, ?, ?) 65 Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) 66 Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) 67 Hibernate: update student set gid=? where sid=? 68 Hibernate: update student set gid=? where sid=? 69 * 70 * 71 */ 72 public static void add(){ 73 Grade g = new Grade("Java一班","Java软件开发一班"); 74 Student stu1 = new Student("张三","男"); 75 Student stu2 = new Student("穆女神","女"); 76 77 //将这两个学生添加到班级中 78 //如果希望在学生表中添加对应的班级编号,需要在班级中添加学生,建立关联关系 79 g.getStudents().add(stu1); //set集合students集合汇总添加,是Grade中的属性 80 g.getStudents().add(stu2); 81 82 //得到会话 83 Session session = HibernateUtil.getSession(); 84 //开启事务 85 Transaction tx = (Transaction) session.beginTransaction(); 86 //保存班级,学生 87 session.save(g); 88 session.save(stu1); 89 session.save(stu2); 90 //提交事务 91 tx.commit(); 92 //关闭session 93 HibernateUtil.closeSession(session); 94 /* 95 * 总结: 96 * 1、新建班级对象和学生对象 97 * 2、将学生对象加入班级对象属性中的学生集合中 98 * 3、调用Session对象保存班级对象和学生对象 99 * save学生对象是把学生信息添加到学生表中 100 * save班级对象是把班级信息添加到班级表中 101 * 将学生对象加入班级对象属性中的学生集合中:其实是为了和映射文件一起完成主外键的连接 102 * 103 */ 104 } 105 106 //查询班级中包含的学生,根据班级获取对应的信息 107 /* 108 * 方法测试对应的输出结果: 109 * Hibernate: select grade0_.gid as gid1_0_0_, grade0_.gname as gname2_0_0_, grade0_.gdesc as gdesc3_0_0_ from grade grade0_ where grade0_.gid=? 110 * Java一班,Java软件开发一班 111 * Hibernate: select students0_.gid as gid4_1_0_, students0_.sid as sid1_1_0_, students0_.sid as sid1_1_1_, students0_.sname as sname2_1_1_, students0_.sex as sex3_1_1_ from student students0_ where students0_.gid=? 112 * 穆女神,女 113 * 张三,男 114 */ 115 public static void findStudentsByGrade(){ 116 //1、建立会话 117 Session session=HibernateUtil.getSession(); 118 //2、通过session从数据库取出班级消息 119 Grade grade= session.get(Grade.class, 1); 120 System.out.println(grade.getGname()+","+grade.getGdesc()); 121 //3、从班级消息中取出学生消息,其实就已经达到目的了 122 Set<Student> students=grade.getStudents(); 123 //4、for遍历输出学生的消息 124 for (Student student : students) { 125 System.out.println(student.getSname()+","+student.getSex()); 126 } 127 /* 128 * 总结: 129 * 1、 130 * 其实核心语句就是Session的get方法,因为这个本事就是一个查询啊 131 * get里面的一个参数是类,那么另一个参数就是主键,类对应的表的主键 132 * 同理,后面的改就是先get,然后update 133 * 删就直接delete对应的类对象就好 134 * 2、 135 * 通过session给对象发送sql,连接数据库,返回数据库消息,这些都是session给对象来完成的 136 * 我们只用享受胜利的果实即可 137 * 138 */ 139 } 140 141 //修改学生信息 142 //这里将学生信息添加到一个新的班级 143 /* 144 * 心得: 145 * 前面总结和一下之后,他这里说啥我能接上下面的 146 * 147 * 方法测试对应的输出结果: 148 Hibernate: select student0_.sid as sid1_1_0_, student0_.sname as sname2_1_0_, student0_.sex as sex3_1_0_ from student student0_ where student0_.sid=? 149 Hibernate: select max(gid) from grade 150 Hibernate: insert into grade (gname, gdesc, gid) values (?, ?, ?) 151 Hibernate: update student set gid=? where sid=? 152 * 153 */ 154 public static void update(){ 155 //这里数据库的结果是班级表里面多了下面的这一条记录 156 //并且对应的学生也修改到了这个班级 157 Grade grade = new Grade("Java二班","Java软件开发二班"); 158 //开启事务 159 Session session=HibernateUtil.getSession(); 160 //因为是进行的数据库的更新,所以必须开启事务 161 Transaction transaction= session.beginTransaction(); 162 //这里是Session得到的是学生表中的信息 163 Student student=session.get(Student.class, 1); 164 grade.getStudents().add(student); 165 session.save(grade); 166 transaction.commit(); 167 HibernateUtil.closeSession(session); 168 169 /* 170 * 总结: 171 * 1、不管对数据库的什么操作,首先肯定要先打开Session 172 * 2、更新就是先get,后update,但是在这里是save, 173 * 3、但凡修改数据库的,加上事务,事务开了肯定也要关闭 174 * 4、因为这里是映射,所以这里还要在班级中加入学生对象 175 * 176 */ 177 178 } 179 180 //删除学生信息 181 /* 182 * 总结: 183 * 得益于前面的总结,这里是自己写的,而且和他写的一样 184 * 自己写的时候还是犹豫了一下要不要开transaction 185 * 但是对数据库的修改肯定是要开session的 186 * 187 * 方法测试对应的输出结果: 188 Hibernate: select student0_.sid as sid1_1_0_, student0_.sname as sname2_1_0_, student0_.sex as sex3_1_0_ from student student0_ where student0_.sid=? 189 Hibernate: delete from student where sid=? 190 * 在数据库的表中成功的删除了主键为4的学生 191 */ 192 public static void delete(){ 193 194 Session session = HibernateUtil.getSession(); 195 //因为是进行的数据库的改变的操作,所以必须开启事务 196 Transaction transaction= session.beginTransaction(); 197 Student student = session.get(Student.class, 4); 198 session.delete(student); 199 transaction.commit(); 200 HibernateUtil.closeSession(session); 201 } 202 203 }
文件对应的目录结构如下