Hibernate 系列 03 - 使用Hibernate完成持久化操作

 

引导目录:

  Hibernate 系列教程 目录

 

  康姆昂,北鼻,来此狗。动次打次,Hibernate继续走起、

 

目录:

  1. 使用Hibernate实现按主键查询
  2. 使用Hibernate实现数据库的增、删、改操作
    2.1 使用Hibernate实现增加操作
    2.2 使用Hibernate实现修改、删除操作
      2.2.1 使用Hibernate实现修改操作
      2.2.2 使用Hibernate实现删除操作
  3. 技能训练

 

  为工程准备了Hibernate环境后,就可以通过Hibernate API操纵数据库。Hibernate内部也是采用JDBC来访问数据库的。

  如下图就是JDBC API及Hibernate API方式来访问数据库:

 Hibernate 系列 03 - 使用Hibernate完成持久化操作_第1张图片

 

使用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,代码如下所示:

 1 package com.geeksss.HibernateStudy.util;
 2 
 3 import org.hibernate.Session;
 4 import org.hibernate.SessionFactory;
 5 import org.hibernate.cfg.Configuration;
 6 
 7 public class HibernateUtil {
 8     // 初始化一个ThreadLocal对象,ThreadLocal对象有get()、set()方法
 9     private static final ThreadLocal sessionTL = new ThreadLocal();
10     private static Configuration configuration;
11     private static final SessionFactory sessionFactory;
12     static{
13         try{
14             configuration = new Configuration().configure();
15             sessionFactory = configuration.buildSessionFactory();
16         }catch(Throwable ex){
17             ex.printStackTrace();
18             throw new ExceptionInInitializerError(ex);
19         }
20     }
21     public static Session currentSession(){
22         /* 
23          * sessionTL的get()方法根据当前县城返回其对应的线程内部变量,即Session对象。
24          * 多线程情况下共享数据库连接是不安全的。
25          * ThreadLoca保证了每个线程都有自己独立的Session对象。
26          */
27         Session session = (Session)sessionTL.get();
28         /*
29          * 如果session为null,则打开一个新的session
30          * 如果该线程是初次访问,session是null,则创建一个Session对象
31          */
32         if(session==null){
33             session = sessionFactory.openSession();    // 创建一个Session对象
34             sessionTL.set(session);    // 保存该Session对象到ThreadLocal中
35         }
36         return session;    // 如果当前线程已经访问过数据库,则从sessionTL中get()就可以获取该线程上次获取过的Session对象。
37     }
38     /**
39      * 关闭session
40      * 首先调用sessionTL.get()方法获取Session对象;
41      * 接着调用sessionTL.set(null)方法,把sessionTL管理的Session对象置为null;
42      * 最后关闭Session。
43      */
44     public static void closeSession(){
45         Session session = (Session)sessionTL.get();
46         sessionTL.set(null);
47         session.close();
48     }
49 }
HibernateUtil.java (Hibernate工具类)

 

通过ThreadLocal类,既实现了多线程并发,同时,也实现了Singleton单例模式。

 

 

 

1. 使用Hibernate实现按主键查询

在进行修改或删除操作时,应先加载对象,然后再执行修改或删除操作。

Hibernate提供了两种方法按照主键加载对象:get()和load()方法、

  • Object get(Class clazz, Serializable id)
  • Object load(Class theClass, Serializable id)

 

虽然两个方法都能够加载对象,但是他们是有区别的。

下面以部门表为例,通过两段代码讲解他们的区别:

 

(1) get()方法加载部门对象的代码如下:

 1 package com.geeksss.HibernateStudy.test;
 2 
 3 import org.hibernate.HibernateException;
 4 import org.hibernate.Session;
 5 import org.hibernate.SessionFactory;
 6 import org.hibernate.cfg.Configuration;
 7 
 8 import com.geeksss.HibernateStudy.entity.Dept;
 9 import com.geeksss.HibernateStudy.entity.Users;
10 import com.geeksss.HibernateStudy.util.HibernateUtil;
11 
12 public class Test {
13     public static void main(String[] args) {
14 
15         Configuration cfg = null;
16         SessionFactory sessionFactory = null;
17         Session session = null;
18         
19         try {
20             // 读取配置文件
21             cfg = new Configuration().configure();    
22             // 创建SessionFactory
23             sessionFactory = cfg.buildSessionFactory();    
24             // 打开session;
25             session = sessionFactory.openSession();
26             // 加载数据操作
27             Users user = (Users)session.get(Users.class, new Integer("4"));
28             // 输出操作
29             System.out.println("使用get()方式获取id为4的用户是:"+user.getName());
30         } catch (HibernateException e) {
31             e.printStackTrace();
32         }finally{
33             if(null!=session){
34                 session.close();
35             }
36         }
37         
38     } 
39 }
使用Session.get()方式获取数据

运行效果如图:

 Hibernate 系列 03 - 使用Hibernate完成持久化操作_第2张图片

 

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

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第3张图片

 

  到此,可能大家肯定会想,为什么查询一个数据,会有两种方式呢?

  希望大家明白:学一个东西,不管是什么,既然存在,那么就有它存在的意义。

  get()和load()亦是如此,肯定有区别的啊~下面我们来演示看一下。。。

 

  现在我的数据库中,User表中只有4条记录:

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第4张图片

 

  下面我们分别使用get()和load()获取id为10的对象并输出,看一下结果。

  1.get()方式,查询返回null:

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第5张图片

 

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

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第6张图片

 

  异常信息为: org.hibernate.ObjectNotFoundExceptionNo row with the given identifier exists: [com.geeksss.HibernateStudy.entity.Users#10]

  即:对象未找到。

 

由此,我们得知:

当使用Session的get()方法时,如果加载的数据不存在,get()方法会返回一个null;但是使用load()方法,若加载的数据不存在,则会抛出异常。

这是get()方法和load()方法的区别之一,两个方法的其他区别,我们后面会慢慢讲到。

  

 

 

 2. 使用Hibernate实现数据库的增、删、改操作

2.1 使用Hibernate实现增加用户记录

  增加操作的测试代码如下:

 1 package com.geeksss.HibernateStudy.test;
 2 
 3 import org.hibernate.HibernateException;
 4 import org.hibernate.Session;
 5 import org.hibernate.SessionFactory;
 6 import org.hibernate.Transaction;
 7 import org.hibernate.cfg.Configuration;
 8 
 9 import com.geeksss.HibernateStudy.entity.Users;
10 
11 public class Test {
12     public static void main(String[] args) {
13         Configuration cfg = null;
14         SessionFactory sessionFactory = null;
15         Session session = null;
16         Transaction transaction = null;
17                 
18         Users user = new Users();                        // 实例化一个对象 并赋值
19         user.setName("李四");
20         user.setPassword("ls123456");
21         user.setTelephone("13800138000");
22         user.setUsername("lisi");
23         user.setisAdmin(false);
24         
25         try { 
26             cfg = new Configuration().configure();        // 读取配置文件
27             sessionFactory = cfg.buildSessionFactory();    // 创建SessionFactory
28             session = sessionFactory.openSession();        // 打开session;
29             transaction = session.beginTransaction();    // 开启一个事务
30             session.save(user);                            // 持久化操作
31             transaction.commit();                        // 提交事务
32         } catch (HibernateException e) {
33             e.printStackTrace(); 
34             transaction.rollback();                        // 回滚事务
35         }finally{
36             if(null!=session) session.close();             // 关闭session
37         }
38         
39     } 
40 }

与JDBC一样,持久化操作放在try中,如果正常则提交,如果异常则进入catch回滚,最后关闭session。

不过,运行出现异常,结果如下:

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第7张图片

 

  仔细观察,我们发现,在控制台中,插入的SQL语句正确打印,但是出错,错误信息显示:“当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'Users' 中的标识列插入显式值。

  很明显,在这里我们插入数据的时候,并没有通过user.setId(xxx)来为其设置编号,那么也就是默认的0。

  打开Users.hbm.xml映射文件,我们发现主键的生成策略我们设置的是“assigned”,也就是由应用程序控制,不用Hibernate干涉。(上节介绍过)

 

  而在这里,我们SQL Server中的Users主键是自动增长的,因此,我们设置为“identity”(自增)或“native”(自动识别)都是可以的。

  设置完映射文件的代码如下:

 1 xml version="1.0" encoding="UTF-8"?>
 2 DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 
 6 <hibernate-mapping package="com.geeksss.HibernateStudy.entity">
 7     <class name="Users" table="Users">
 8         <id name="id" type="java.lang.Integer" column="Id">
 9             <generator class="identity">generator>
10         id>
11         <property name="name" type="java.lang.String" column="Name">property>
12         <property name="password" type="java.lang.String" column="Password">property>
13         <property name="telephone" type="java.lang.String" column="Telephone">property>
14         <property name="username" type="java.lang.String" column="Username">property>
15         <property name="isAdmin" type="java.lang.Boolean" column="IsAdmin">property>
16     class>
17 hibernate-mapping>

 

再次运行程序,插入成功:

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第8张图片

 

 

 

2.2 使用Hibernate实现用户信息的修改、删除

  下面学习如何使用Hibernate修改和删除数据。

  对于Hibernate这种ORM工具,操作都是针对对象的。

  要修改和删除数据,首先要获得数据,然后再进行修改和删除数据。

 

2.2.1 使用Hibernate修改用户数据

实例代码如下:

 1 package com.geeksss.HibernateStudy.test;
 2 
 3 import org.hibernate.HibernateException;
 4 import org.hibernate.Session;
 5 import org.hibernate.SessionFactory;
 6 import org.hibernate.Transaction;
 7 import org.hibernate.cfg.Configuration;
 8 
 9 import com.geeksss.HibernateStudy.entity.Dept;
10 import com.geeksss.HibernateStudy.entity.Users;
11 import com.geeksss.HibernateStudy.util.HibernateUtil;
12 
13 public class Test {
14     public static void main(String[] args) {
15 
16         Configuration cfg = null;
17         SessionFactory sessionFactory = null;
18         Session session = null;
19         Transaction transaction = null; 
20         try {
21             cfg = new Configuration().configure();    // 读取配置文件
22             sessionFactory = cfg.buildSessionFactory();    // 创建SessionFactory
23             session = sessionFactory.openSession();    // 打开session;
24             
25             Users user = (Users)session.get(Users.class, new Integer("4"));    // 加载数据操作
26             System.out.println("修改之前编号4用户姓名是:"+user.getName());    // 输出操作
27             
28             transaction = session.beginTransaction();    // 创建事务
29             user.setName("测试修改");    // 修改对象
30             transaction.commit();    // 提交事务 完成修改
31             
32             user = (Users)session.get(Users.class, new Integer("4"));    // 重新加载数据
33             System.out.println("修改之后编号4用户姓名是:"+user.getName());    // 输出操作
34         } catch (HibernateException e) {
35             e.printStackTrace();
36             if(null != transaction){
37                 transaction.rollback();
38             }
39         }finally{
40             if(null!=session){
41                 session.close();
42             }
43         }
44         
45     } 
46 }
使用Hibernate实现修改Users数据

执行结果如下:

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第9张图片

 

  在使用Hibernate修改数据时,首先要加载对象,然后修改对象的属性,最后提交事务。

  Hibernate会生成并执行修改的SQL语句,其中的原理会在后面慢慢讲到滴~

 

 

 

2.2.2 使用Hibernate实现删除Users数据

实例代码如下:

 1 package com.geeksss.HibernateStudy.test;
 2 
 3 import org.hibernate.HibernateException;
 4 import org.hibernate.Session;
 5 import org.hibernate.SessionFactory;
 6 import org.hibernate.Transaction;
 7 import org.hibernate.cfg.Configuration;
 8 
 9 import com.geeksss.HibernateStudy.entity.Dept;
10 import com.geeksss.HibernateStudy.entity.Users;
11 import com.geeksss.HibernateStudy.util.HibernateUtil;
12 
13 public class Test {
14     public static void main(String[] args) {
15 
16         Configuration cfg = null;
17         SessionFactory sessionFactory = null;
18         Session session = null;
19         Transaction transaction = null; 
20         try {
21             cfg = new Configuration().configure();    // 读取配置文件
22             sessionFactory = cfg.buildSessionFactory();    // 创建SessionFactory
23             session = sessionFactory.openSession();    // 打开session;
24             
25             Users user = (Users)session.get(Users.class, new Integer("4"));    // 加载数据操作
26             System.out.println("删除之前编号4用户是:"+user);    // 输出操作
27             
28             transaction = session.beginTransaction();    // 创建事务
29             session.delete(user);    // 删除user对象
30             transaction.commit();    // 提交事务 完成删除
31             
32             user = (Users)session.get(Users.class, new Integer("4"));    // 重新加载数据
33             System.out.println("删除之后编号4用户是:"+user);    // 输出操作
34         } catch (HibernateException e) {
35             e.printStackTrace();
36             if(null != transaction){
37                 transaction.rollback();
38             }
39         }finally{
40             if(null!=session){
41                 session.close();
42             }
43         }
44         
45     } 
46 }
使用Hibernate实现删除Users对象

执行结果如下:

Hibernate 系列 03 - 使用Hibernate完成持久化操作_第10张图片

 

  与修改类似,删除时也需要先加载数据。

  在使用Hibernate编写持久化代码时,业务不需要再有数据库表、字段等概念。

  从面相业务领域对象的角度,要删除的是某个业务对象。以面相对象的方式编写的代码是Hibernate持久化操作接口设计的一个理念。

 

  需要注意的是,增、删、改操作一定要在事务环境中完成。

 

 

 

 

3. 技能训练 - 在租房网系统中实现用户表的增删改查操作

在上一节我们已经搭建好的Hibernate环境中,使用Hibernate实现用户记录的增加、修改、删除和查询操作。

要求按照用户编号查询指定的用户记录。

 

 

 

 

  同志们,有错提错,代码撸起吧~ 呵呵。

 

你可能感兴趣的:(Hibernate 系列 03 - 使用Hibernate完成持久化操作)