Hibernate 系列 03 - 使用Hibernate完成持久化操作
引导目录:
康姆昂,北鼻,来此狗。动次打次,Hibernate继续走起、
目录:
为工程准备了Hibernate环境后,就可以通过Hibernate API操纵数据库。Hibernate内部也是采用JDBC来访问数据库的。
如下图就是JDBC API及Hibernate API方式来访问数据库:

使用Hibernate操作数据库包括7个步骤:
(1)读取并解析配置文件
Configuration cfg = new Configuration().configure();
根据默认位置的Hibernate配置文件的配置信息,构建Configuration对象。
Configuration负责管理Hibernate的配置信息。
(2)读取并解析映射信息,创建SessionFactory对象:
SessionFactory sessionFactory = cfg.buildSessionFactory();
SessionFactory负责创建Session对象。
Configuration对象会根据当前的数据库配置信息,构造SessionFactory对象。
SessionFactory对象一旦构造完毕,则Configuration对象的任何变更将不会影响已经创建的SessionFactory对象。
如果Hibernate配置信息有改动,那么需要基于改动后的Configuration对象重新构建一个SessionFactory对象。
(3)打开Session:
Session session = sessionFactory.openSession(); // 或者使用 sessionFactory.getCurrentSession();
Session是Hibernate持久化操作的基础。Session负责完成对象的持久化操作,它相当于JDBC中的Connection。
Session作为贯穿Hibernate的持久化管理器的核心,提供了众多持久化方法,如save()、delete()、update()、get()、load()等。
通过这些方法,即可透明地完成对象的增删改查(CRUD)。
(4)开始一个事务(增删改操作必须,查询操作可选):
Transaction transaction = session.beginTransaction(); // 打开事务
(5)数据库操作:
session.save(obj); // 将obj对象进行保存操作
(6)结束事务:
transaction.commit(); // 提交事务
(7)关闭session:
session.close(); // 关闭session
如果在Hibernate配置文件中,参数current_session_context_class设置为thread,并采用SessionFactory的getCurrentSession()方法获得Session对象,则不需要执行session.close()方法。
资料:
在项目开发过程中,通常使用工具类来管理SessionFactory和Session,代码如下所示:
package com.geeksss.HibernateStudy.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { // 初始化一个ThreadLocal对象,ThreadLocal对象有get()、set()方法 private static final ThreadLocal sessionTL = new ThreadLocal(); private static Configuration configuration; private static final SessionFactory sessionFactory; static{ try{ configuration = new Configuration().configure(); sessionFactory = configuration.buildSessionFactory(); }catch(Throwable ex){ ex.printStackTrace(); throw new ExceptionInInitializerError(ex); } } public static Session currentSession(){ /* * sessionTL的get()方法根据当前县城返回其对应的线程内部变量,即Session对象。 * 多线程情况下共享数据库连接是不安全的。 * ThreadLoca保证了每个线程都有自己独立的Session对象。 */ Session session = (Session)sessionTL.get(); /* * 如果session为null,则打开一个新的session * 如果该线程是初次访问,session是null,则创建一个Session对象 */ if(session==null){ session = sessionFactory.openSession(); // 创建一个Session对象 sessionTL.set(session); // 保存该Session对象到ThreadLocal中 } return session; // 如果当前线程已经访问过数据库,则从sessionTL中get()就可以获取该线程上次获取过的Session对象。 } /** * 关闭session * 首先调用sessionTL.get()方法获取Session对象; * 接着调用sessionTL.set(null)方法,把sessionTL管理的Session对象置为null; * 最后关闭Session。 */ public static void closeSession(){ Session session = (Session)sessionTL.get(); sessionTL.set(null); session.close(); } }HibernateUtil.java (Hibernate工具类)
通过ThreadLocal类,既实现了多线程并发,同时,也实现了Singleton单例模式。
1. 使用Hibernate实现按主键查询
在进行修改或删除操作时,应先加载对象,然后再执行修改或删除操作。
Hibernate提供了两种方法按照主键加载对象:get()和load()方法、
- Object get(Class clazz, Serializable id)。
- Object load(Class theClass, Serializable id)。
虽然两个方法都能够加载对象,但是他们是有区别的。
下面以部门表为例,通过两段代码讲解他们的区别:
(1) get()方法加载部门对象的代码如下:
package com.geeksss.HibernateStudy.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.geeksss.HibernateStudy.entity.Dept;
import com.geeksss.HibernateStudy.entity.Users;
import com.geeksss.HibernateStudy.util.HibernateUtil;
public class Test {
public static void main(String[] args) {
Configuration cfg = null;
SessionFactory sessionFactory = null;
Session session = null;
try {
// 读取配置文件
cfg = new Configuration().configure();
// 创建SessionFactory
sessionFactory = cfg.buildSessionFactory();
// 打开session;
session = sessionFactory.openSession();
// 加载数据操作
Users user = (Users)session.get(Users.class, new Integer("4"));
// 输出操作
System.out.println("使用get()方式获取id为4的用户是:"+user.getName());
} catch (HibernateException e) {
e.printStackTrace();
}finally{
if(null!=session){
session.close();
}
}
}
}
使用Session.get()方式获取数据
运行效果如图:

(2) load()方法加载数据,只需要将get换为load即可,结果不变。如图:

到此,可能大家肯定会想,为什么查询一个数据,会有两种方式呢?
希望大家明白:学一个东西,不管是什么,既然存在,那么就有它存在的意义。
get()和load()亦是如此,肯定有区别的啊~下面我们来演示看一下。。。
现在我的数据库中,User表中只有4条记录:

下面我们分别使用get()和load()获取id为10的对象并输出,看一下结果。
1.get()方式,查询返回null:

2.load()方式,查询返回如下异常:

异常信息为: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.geeksss.HibernateStudy.entity.Users#10]
即:对象未找到。
由此,我们得知:
当使用Session的get()方法时,如果加载的数据不存在,get()方法会返回一个null;但是使用load()方法,若加载的数据不存在,则会抛出异常。
这是get()方法和load()方法的区别之一,两个方法的其他区别,我们后面会慢慢讲到。
2. 使用Hibernate实现数据库的增、删、改操作
2.1 使用Hibernate实现增加用户记录
增加操作的测试代码如下:
package com.geeksss.HibernateStudy.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.geeksss.HibernateStudy.entity.Users;
public class Test {
public static void main(String[] args) {
Configuration cfg = null;
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
Users user = new Users(); // 实例化一个对象 并赋值
user.setName("李四");
user.setPassword("ls123456");
user.setTelephone("13800138000");
user.setUsername("lisi");
user.setisAdmin(false);
try {
cfg = new Configuration().configure(); // 读取配置文件
sessionFactory = cfg.buildSessionFactory(); // 创建SessionFactory
session = sessionFactory.openSession(); // 打开session;
transaction = session.beginTransaction(); // 开启一个事务
session.save(user); // 持久化操作
transaction.commit(); // 提交事务
} catch (HibernateException e) {
e.printStackTrace();
transaction.rollback(); // 回滚事务
}finally{
if(null!=session) session.close(); // 关闭session
}
}
}
与JDBC一样,持久化操作放在try中,如果正常则提交,如果异常则进入catch回滚,最后关闭session。
不过,运行出现异常,结果如下:

仔细观察,我们发现,在控制台中,插入的SQL语句正确打印,但是出错,错误信息显示:“当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'Users' 中的标识列插入显式值。”
很明显,在这里我们插入数据的时候,并没有通过user.setId(xxx)来为其设置编号,那么也就是默认的0。
打开Users.hbm.xml映射文件,我们发现主键的生成策略我们设置的是“assigned”,也就是由应用程序控制,不用Hibernate干涉。(上节介绍过)
而在这里,我们SQL Server中的Users主键是自动增长的,因此,我们设置为“identity”(自增)或“native”(自动识别)都是可以的。
设置完映射文件的代码如下:
<?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 package="com.geeksss.HibernateStudy.entity">
<class name="Users" table="Users">
<id name="id" type="java.lang.Integer" column="Id">
<generator class="identity"></generator>
</id>
<property name="name" type="java.lang.String" column="Name"></property>
<property name="password" type="java.lang.String" column="Password"></property>
<property name="telephone" type="java.lang.String" column="Telephone"></property>
<property name="username" type="java.lang.String" column="Username"></property>
<property name="isAdmin" type="java.lang.Boolean" column="IsAdmin"></property>
</class>
</hibernate-mapping>
再次运行程序,插入成功:

2.2 使用Hibernate实现用户信息的修改、删除
下面学习如何使用Hibernate修改和删除数据。
对于Hibernate这种ORM工具,操作都是针对对象的。
要修改和删除数据,首先要获得数据,然后再进行修改和删除数据。
2.2.1 使用Hibernate修改用户数据
实例代码如下:
package com.geeksss.HibernateStudy.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.geeksss.HibernateStudy.entity.Dept;
import com.geeksss.HibernateStudy.entity.Users;
import com.geeksss.HibernateStudy.util.HibernateUtil;
public class Test {
public static void main(String[] args) {
Configuration cfg = null;
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
cfg = new Configuration().configure(); // 读取配置文件
sessionFactory = cfg.buildSessionFactory(); // 创建SessionFactory
session = sessionFactory.openSession(); // 打开session;
Users user = (Users)session.get(Users.class, new Integer("4")); // 加载数据操作
System.out.println("修改之前编号4用户姓名是:"+user.getName()); // 输出操作
transaction = session.beginTransaction(); // 创建事务
user.setName("测试修改"); // 修改对象
transaction.commit(); // 提交事务 完成修改
user = (Users)session.get(Users.class, new Integer("4")); // 重新加载数据
System.out.println("修改之后编号4用户姓名是:"+user.getName()); // 输出操作
} catch (HibernateException e) {
e.printStackTrace();
if(null != transaction){
transaction.rollback();
}
}finally{
if(null!=session){
session.close();
}
}
}
}
使用Hibernate实现修改Users数据
执行结果如下:

在使用Hibernate修改数据时,首先要加载对象,然后修改对象的属性,最后提交事务。
Hibernate会生成并执行修改的SQL语句,其中的原理会在后面慢慢讲到滴~
2.2.2 使用Hibernate实现删除Users数据
实例代码如下:
package com.geeksss.HibernateStudy.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.geeksss.HibernateStudy.entity.Dept;
import com.geeksss.HibernateStudy.entity.Users;
import com.geeksss.HibernateStudy.util.HibernateUtil;
public class Test {
public static void main(String[] args) {
Configuration cfg = null;
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
cfg = new Configuration().configure(); // 读取配置文件
sessionFactory = cfg.buildSessionFactory(); // 创建SessionFactory
session = sessionFactory.openSession(); // 打开session;
Users user = (Users)session.get(Users.class, new Integer("4")); // 加载数据操作
System.out.println("删除之前编号4用户是:"+user); // 输出操作
transaction = session.beginTransaction(); // 创建事务
session.delete(user); // 删除user对象
transaction.commit(); // 提交事务 完成删除
user = (Users)session.get(Users.class, new Integer("4")); // 重新加载数据
System.out.println("删除之后编号4用户是:"+user); // 输出操作
} catch (HibernateException e) {
e.printStackTrace();
if(null != transaction){
transaction.rollback();
}
}finally{
if(null!=session){
session.close();
}
}
}
}
使用Hibernate实现删除Users对象
执行结果如下:

与修改类似,删除时也需要先加载数据。
在使用Hibernate编写持久化代码时,业务不需要再有数据库表、字段等概念。
从面相业务领域对象的角度,要删除的是某个业务对象。以面相对象的方式编写的代码是Hibernate持久化操作接口设计的一个理念。
需要注意的是,增、删、改操作一定要在事务环境中完成。
3. 技能训练 - 在租房网系统中实现用户表的增删改查操作
在上一节我们已经搭建好的Hibernate环境中,使用Hibernate实现用户记录的增加、修改、删除和查询操作。
要求按照用户编号查询指定的用户记录。
同志们,有错提错,代码撸起吧~ 呵呵。
Hibernate 系列 03 - 使用Hibernate完成持久化操作的更多相关文章
- hibernate系列笔记(1)---Hibernate增删改查
Hibernate增删改查 1.首先我们要知道什么是Hibernate Hibernate是一个轻量级的ORMapping对象.主要用来实现Java和数据库表之间的映射,除此之外还提供数据查询和数据获 ...
- hibernate系列笔记(2)---Hibernate的核心API
Hibernate的核心API 一般我们通过hibernate进行操作的时候,都会遵循下面的流程,那么接下来我对每一个步骤进行讲解: 1 public void testInsert() { 2 // ...
- Hibernate 系列 学习笔记 目录 (持续更新...)
前言: 最近也在学习Hibernate,遇到的问题差不多都解决了,顺便把学习过程遇到的问题和查找的资料文档都整理了一下分享出来,也算是能帮助更多的朋友们了. 最开始使用的是经典的MyEclipse,后 ...
- Hibernate 系列 07 - Hibernate中Java对象的三种状态
引导目录: Hibernate 系列教程 目录 1. Java对象的三种状态 当应用通过调用Hibernate API与框架发生交互时,需要从持久化的角度关注应用对象的生命周期. 持久化声明周期是Hi ...
- Hibernate 系列教程3-单表操作
工程截图 hibernate.cfg.xml <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Conf ...
- Hibernate 系列 02 - Hibernate介绍及其环境搭建
引导目录: Hibernate 系列教程 目录 昨晚喝多了,下午刚清醒,继续搞Hibernate.走起. 觉得还行的话,记得点赞哈,给我这个渣渣点学习的动力.有错误的话也请指出,省的我在错误上走了不归 ...
- Hibernate 系列 05 - Session 类
引导目录: Hibernate 系列教程 目录 前言: Session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库的存取都与Session息息相关. 就如同在编写JDBC时需要关 ...
- 【SSH框架】之Hibernate系列一
微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1.Hibernate框架概述 (1).什么是HibernateHibernate是一个开放源代 ...
- Hibernate 系列 01 - 框架技术 (介绍Hibernate框架的发展由来)
引导目录: Hibernate 系列教程 目录 本篇导航: 为什么学习框架技术 框架的概念 主流框架的介绍 1.为什么学习框架技术 如何制作一份看上去具有专业水准的PPT文档呢?一个简单的方法就是使用 ...
随机推荐
- 死去活来,而不变质:Domain Model(领域模型) 和 EntityFramework 如何正确进行对象关系映射?
写在前面 阅读目录: 设计误区 数据库已死 枚举映射 关联映射 后记 在上一篇<一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?>博文中, ...
- your password has expired.to log in you must change it
今天应用挂了,log提示密码过期.客户端连接不上. 打开mysql,执行sql语句提示密码过期 执行set password=new password('123456'); 提示成功,但客户端仍然连接 ...
- [MongoDB] 32Bit构建上文件大小限制问题
一. 问题概述 今天看看爬虫抓取的数据,发现数据无法插入,首先想到的就是32Bit构建的文件大小限制问题,检查一下还真的是.本文把整个检查问题,解决问题的过程记录下来. 问题: "s ...
- C# BS消息推送 负载均衡-SignalR&Redis的配置(三)
1. 前言 本文是根据网上前人的总结得出的. 环境: SignalR2.x,VS2015,Win10 2. 负载均衡配置 配置很简单,只要在startup类中添加Redis的连接就OK. 1)首先,引 ...
- 【MSP是什么】MSP认证之项目群管理学习总结
首先要说的是,我这篇体会是针对一定的背景的,不能算是一种通用的管理方式,只能是我自己的经验总结,能给大家平常的管理提供一点思路,我就很满足了.先说说背景,我所在公司做的是大型桌面应用软件,简单点说就是 ...
- 对jquery操作复选框
摘要:jquery操作复选框.使用更简洁易懂,思路清晰,逻辑更明了,很实用 <!DOCTYPE html> <html> <head> <meta chars ...
- BootStrap_04之jQuery插件(导航、轮播)、以及Less
1.列偏移与列排序: ①列偏移:控制列出现的位置,某列偏移后,后序列会随之偏移--只能右偏移: col-lg/md/sm/xs-offset-*; ②列排序:控制某一列的位置,该列可以左(pull)右 ...
- 编程之美—烙饼排序问题(JAVA)
一.问题描述 星期五的晚上,一帮同事在希格玛大厦附近的"硬盘酒吧"多喝了几杯.程序员多喝了几杯之后谈什么呢?自然是算法问题.有个同事说:"我以前在餐 馆打工,顾 ...
- MUI跨域请求数据的例子:
<, , success: function(data) { ...
- C# 获取Excel中的合并单元格
C# 获取Excel中的合并单元格 我们在制作表格时,有时经常需要合并及取消合并一些单元格.在取消合并单元格时需要逐个查找及取消,比较麻烦.这里分享一个简单的方法来识别Excel中的合并单元格,识别这 ...