jsp hibernate 数据保存操作的原理

数据的保存,更新和删除:
1、Session.save()方法:
Session.save()方法用于实体对象的持久化保存,也就是说当执行session.save()方法时会生成对应的insert SQL语句,完成数据的保存。如下面的代码:
User user=new User();
user.setName(“zx”);
Transaction tx=session.beginTransaction();
session.save(user);
tx.commit();
当执行到session.save()方法时,Hibernate并不会马上生成insert SQL语句来进行数据的保存,而是当稍后清理session的缓存时才有可能执行insert SQL语句,那么session.save()方法到底会执行哪些步骤呢?请看进行了如下总结:
一、 在session的内部缓存中寻找保存对象,如果找到了,则认为此数据已经保存(曾经执行过insert操作),实体对象已经处于persistent状态,直接返回。此时即使数据相比之前的状态发生了变化,也将在事务提交时由脏数据检查来判定是否需要执行update操作。
二、 如果实体对象实现了lifecycle接口,那么将执行待保存对象的onSave()方法。
三、 如果实体对象实现了Validatable接口,那么将会执行相应的validate()方法。
四、 如果存在拦截器对象,那么将会执行Interceptor.onSave()方法。
五、 构造insert SQL语句完成数据保存。
六、 数据保存成功后,设定实体对象的id为插入记录的id。
七、 将保存后的实体对象纳入Hibernate的内部缓存(一级缓存)。注意Hibernate不会把保存后的实体对象纳入二级缓存,因为刚刚保存过的实体对象很可能在之后被修改,缓存的频繁更新以及带来的同步问题代价,超出了缓存该对象所带来的收益。
八、 最后如果该对象有关联对象,那么将会递归处理该级联对象。

1、 Session.update()方法:
前面我在实体对象状态转化部分曾经讲过,session.update()方法能够将一个处于游离状态的对象,重新纳入Hibernate的内部缓存,变成持久化对象。如下面的代码:
Configuration cfg = new Configuration();
SessionFactory sf=cfg. configure().buildSessionFactory();
Customer customer=new Customer(“zx”,27,images);//customer对象处于自由状态
Session session=sf.openSession();

Transaction tx=session.beginTransaction();
session.save(customer);//保存后customer对象处于持久化状态
session.flush();//清空缓存后customer对象处于游离状态
tx.commit();
session.close();

Session session2=sf.openSession();
Transaction tx2=session2.beginTransaction();
session2.update(customer);//通过调用update()方法将游离状态的customer对象,再次转化成持久化状态
session2.delete(customer);//调用delete()方法后,当清空缓存时,会将customer对象移出缓存,同时会在数据库中生成delete事务,来删除customer对象对应的数据记录
tx.commit();
session.close();
那么这个方法到底执行了哪些步骤呢?它会按照下面的步骤进行操作:
一、 首先会在缓存中寻找需要更新的实体对象,如果找到就立刻返回,从这里我们可以看出如果对一个已经处于persistent的实体对象执行update()方法,将不会产生任何作用。
二、 然后当提交事务进行缓存清理时,将会通过脏数据检查,确定变化的属性,然后生成update SQL语句完成数据的更新。
这里有一个问题我们要强调一下,那就是只要通过update()方法将一个游离对象与session相关联,那么不论这个游离的实体对象的属性是否发生改变,都会执行update SQL语句。如下面的代码:

Transaction tx=session.beginTransaction();
session.update(customer);
tx.commit();
session.close();
在这段代码中并没有修改customer对象的任何属性值,但是也会执行一个update SQL语句,如果你希望在没有改变实体对象属性值的情况下不去执行update SQL语句,那么你要开启实体对象<class>元素的”select-before-update”属性,将其设置为”true”,这个属性默认为”false”。如下进行配置:
<class name=”com.neusoft.entity.Customer” table=”customer” select-before-update=”true”>
如果启用了这个属性配置,那么在清理session缓存之前,会首先执行类似如下的一条SQL语句:
Select * from customer where id='1';
查询处所有的customer实体在数据库中对应的属性值,然后逐条与缓存中属性值进行比较,如果发生了改变,那么将会生成update操作进行数据更新,如果没有发生改变那么将不会进行update操作。要跟据实际需求情况来决定是否开启这个选项,如果实体对象的属性不会经常发生改变,那么就应该开启这个选项,以免执行多余的update操作。如果实体对象的属性会经常发生改变,那么就没必要开启这个选项,以免在执行update操作前再执行多余的select语句。

注:(1)、当执行对一个游离实体对象执行session.update()操作时,如果在数据库中不存在这个实体对应的纪录,那么这个操作将会抛出异常。
(2)、当执行session.update()方法将一个游离对象与session关联时,如果此时在缓存中已经存在了与该实体对象具有相同OID的持久化对象,那么这个方法会抛出异常。如下面代码:
Customer customer1=new Customer(“1”,“zx”,27,images);
Session session1=sf.openSession();
Transaction tx=session1.beginTransaction();
session.save(customer1);
session.flush();
tx.commit();
session1.close();

Session session2=sf.openSession();
Transaction tx2=session2.beginTransaction();
Customer othercustomer=(Customer)session2.load(Customer.class,”1”);
session2.update(customer1)
tx2.commit();
session2.close();
当再次将游离对象customer1与session2关联时,此时因为load()操作,在缓存已经加载了一个和customer1具有相同OID的othercustomer对象,此时由于Hibernate缓存的对象缓存机制不允许把OID相同的对象缓存,所以会抛出异常。
2、 Session.saveOrUpdate():
这个方法包含了save()方法和update()方法的特点,如果传入该方法的是一个游离对象,那么这个方法就会执行update操作,如果传入该方法的是一个临时对象,那么这个方法就会执行insert操作。这个方法幕后的工作原理如下:
a) 首先在缓存寻找,如果找到待保存的操作就直接返回。
b) 如果实体实现了拦截方法,那么就执行isUnsaved()方法,判断实体对象状态。
c) 如果实体处于临时状态就执行save(),如果实体处于游离状态那么就执行update()。
这里存在一个问题,那就是Hibernate是怎样判断一个实体是处于游离态还是临时状态的?如果实体满足下面的一个条件,就认为这个实体处于临时状态。
.Java对象的OID值为null。
.如果Java对象具有version属性(将在并发加锁部分讲解)且为null。
.如果实体的<id>设置了属性unsaved-value,而且OID值与unsaved-value值相等。
.如果实体的version属性设置了unsaved-value,并且version属性的值与unsaved-value值相等。
.如果实体实现了Interceptor,而且Interceptor.isUnsaved()方法返回true。
满足这些条件中的一个,这个实体就被认为是临时对象。
3、 Session.delete():
delete()方法用于从数据库中删除一个或一批实体所对应的数据,如果传入的对象是持久化对象,么当清理缓存时,就会执行delete操作。如果传入的是游离对象,那么首先会使该对象与session相关联,然后当清理缓存时,再执行delete操作。看如下代码:
Session session=sessionFactory().openSession();
Transaction tx=session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,”1”);
session.delete(customer);//计划执行一条delete语句
tx.commit();//清理缓存,执行一条delete语句
session.close();//关闭session,这时将会把customer对象从缓存中删除。
如果上面的代码中的customer对象是一个游离对象,那么当执行session.delete()方法时,会首先将游离的customer对象与session相关联,然后再清理缓存时,再执行delete操作。如果你想一次删除多条数据,那么可以采用一个重载的delete()方法:delete(“from Customer c where c.id>'8' ”);这个方法可以删除符合条件的所有数据。

(0)

相关推荐

  • JSP开发中hibernate框架的常用检索方式总结

    总结hibernate框架的常用检索方式 1.hibernate框架的检索方式有以下几种: OID检索:根据唯一标识OID检索数据 对象导航检索:根据某个对象导航查询与该对象关联的对象数据 HQL检索:通过query接口对象查询 QBC检索:通过criteria接口对象查询 SQL检索:通过SQL语句查询  2.HQL检索方式: 查询全部数据:session.createQuery("from 类名"); 根据条件查询:session.createQuery("from 类名

  • jsp hibernate的分页代码第1/3页

    可见使用Hibernate,在进行查询分页的操作上,是具有非常大的灵活性,Hibernate会首先尝试用特定数据库的分页sql,如果没用,再尝试Scrollable,如果不行,最后采用rset.next()移动的办法. (一)pager类 * @(#)Pager.java 2005-5-3 * * Copyright (c) 2005, Jeffrey Hsu */ package com.jeffrey.messagelove; /** * Pager holds the page info.

  • jsp Hibernate入门教程第1/3页

    例如: 复制代码 代码如下: HibernateTest.java import onlyfun.caterpillar.*; import net.sf.hibernate.*; import net.sf.hibernate.cfg.*; import java.util.*; public class HibernateTest { public static void main(String[] args) throws HibernateException { SessionFacto

  • jsp Hibernate批量更新和批量删除处理代码

    以下程序直接通过Hibernate API批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段: tx = session.beginTransaction();Iterator customers=session.find("from Customer c where c.age>0").iterator();while(customers.hasNext()){Customer customer=(Customer)customers.next();customer

  • JSP 开发之hibernate配置二级缓存的方法

    JSP 开发之hibernate配置二级缓存的方法 hibernate二级缓存也称为进程级的缓存或SessionFactory级的缓存. 二级缓存是全局缓存,它可以被所有的session共享. 二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存. 常用的缓存插件 Hibernater二级缓存是一个插件,下面是几种常用的缓存插件: EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了

  • JSP 中Hibernate实现映射枚举类型

    JSP 中Hibernate实现映射枚举类型 问题: Java BO类Gender是枚举类型,想在数据库中存成字符串格式,如何编写hbm.xml? public enum Gender{ UNKNOWN("Unknown"), MALE("Male"), FEMALE("Female"); private String key; private Gender(final String key) { this.key = key; } public

  • JSP开发之hibernate之单向多对一关联的实例

    JSP开发之hibernate之单向多对一关联的实例 一对多的基础上来测试单向多对一的关联 hibernate多对一的关联关系定义: 和单向一对多不同的是:一对多是在意的一方的一方定义set集合,在映射文件中 <set name="" table=""> <key name="" /> <one to many class=" 多的一方的包加类名"/> </set> :单向多对一

  • jsp Hibernate 函数简介

    1.Configuration/SessionFactory/Session Configuration实例代表了一个应用程序中Java类型 到SQL数据库映射的完整集合. Configuration被用来构建一个(不可变的 (immutable))SessionFactory. SessionFactory是线程安全的,创建代价很高. Session是非线程安全的,轻量级的.一个Session对应一个JDBC连接, Session的connection()会获取Session与之对应的数据库连

  • JSP 开发之hibernate的hql查询多对多查询

    JSP 开发之hibernate的hql查询多对多查询 在hibernate的hql查询中,假如说分组信息与试题是多对多关系,那么我们要在hql查询中对含有多个分组信息的试题都要查询出来.并同时查询出相应试题的分组信息.那么此时hql要这样写: String[] groupIds = ojbects[1].toString().split(","); String hql = "SELECT distinct a.id FROM TmEduExamContent a"

  • jsp hibernate 数据保存操作的原理

    数据的保存,更新和删除: 1.Session.save()方法: Session.save()方法用于实体对象的持久化保存,也就是说当执行session.save()方法时会生成对应的insert SQL语句,完成数据的保存.如下面的代码: User user=new User(); user.setName("zx"); Transaction tx=session.beginTransaction(); session.save(user); tx.commit(); 当执行到se

  • Android开发之完成登陆界面的数据保存回显操作实例

    本文实例讲述了Android开发之完成登陆界面的数据保存回显操作.分享给大家供大家参考,具体如下: LoginActivity.java: package com.example.login; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.view.Menu; import android.view

  • Spring和Hibernate的整合操作示例

    本文实例讲述了Spring和Hibernate的整合操作.分享给大家供大家参考,具体如下: 一 web配置 <?xml version="1.0" encoding="GBK"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schem

  • PHP对象链式操作实现原理分析

    本文实例讲述了PHP对象链式操作实现原理.分享给大家供大家参考,具体如下: 什么是链式操作呢?使用jQuery的同学印象应该会很深刻.在jQuery中,我们经常会这样的来操作DOM元素: $("p").css("color").addClass("selected"); 连贯操作看起来的确很酷,也非常的方便代码的阅读.那么在PHP里面是否可以实现呢?答案是肯定的,当然了必须是在OOP中用才行,在过程化的程序中,就没有必要用这种方法了. 在PHP中

  • JSP针对XML文件操作技巧实例分析

    本文实例讲述了JSP针对XML文件操作技巧.分享给大家供大家参考,具体如下: XML(Extensible Markup   Language)可扩展标记语言,这个基础知识在早些已经学习过.而这篇教程为什么把它放在J2EE下边呢,因为他也是J2EE的13规范之一,虽然XML是W3C万维网组织联盟指定的,并做了规范,所以说也是一种规范,我们也必须按照规范来,和JDBC,Servlet,Jsp,Ejb等一样的. 前边的文章已经介绍了XML的一些基础知识,主要是用来存储,传输数据的,但是这些数据我们怎

  • Hibernate单表操作实例解析

    单一主键 assigned:由Java应用程序负责生成(即手工的赋值) native:由底层的数据库自动的生成标示符,如果是MySQL就是auto_increment,如果是Oracle就是sequence,等等 操作的时候还是需要结合hibernate.cfg.xml文件的,因为数据库中的hbm2ddl.auto属性如果是update的时候,设置为主键自增是可以的:但是如果是create的时候,第二次如果不手工的改变,恐怕就要出BUG了. 基本类型 一般来说,按照Java的数据类型进行操作就可

  • Hibernate持久化对象生命周期原理解析

    三态的基本概念 1, 临时状态(Transient):也叫自由态,只存在于内存中,而在数据库中没有相应数据.用new创建的对象,它没有持久化,没有处于Session中,处于此状态的对象叫临时对象: 2, 持久化状态(Persistent):与session关联并且在数据库中有相应数据.已经持久化,加入到了Session缓存中.如通过hibernate语句保存的对象.处于此状态的对象叫持久对象: 3, 游离状态(Detached):持久化对象脱离了Session的对象.如Session缓存被清空的

  • ThinkPHP3.1数据CURD操作快速入门

    1.CURD概述: CURD是一个数据库技术中的缩写词,一般的项目开发的各种参数的基本功能都是CURD.它代表创建(Create).更新(Update).读取(Read)和删除(Delete)操作.CURD 定义了用于处理数据的基本原子操作.之所以将CURD提升到一个技术难题的高度是因为完成一个涉及在多个数据库系统中进行CURD操作的汇总相关的活动,其性能可能会随数据关系的变化而有非常大的差异. CURD在具体的应用中并非一定使用create.update.read和delete字样的方法,但是

  • 很全面的Mysql数据库、数据库表、数据基础操作笔记(含代码)

    Mysql数据库.数据库表.数据基础操作笔记分享给大家,供大家参考,具体内容如下 一.数据库操作 1.创建数据库 Create database db name[数据库选项]; tip:语句要求使用语句结束符";"来结束服务. 标识符(数据库名)命名规则: 大小写取决于当前操作系统. 见名知意,推荐使用下划线法. 标识符的字符: 使用任意字符,数字,甚至中文.但是一些特殊的组合,例如纯数字组合,特殊符号等需使用标识符限定符来包裹. 限定符:反引号`` 中文可以:但要求客户端编码 在my

随机推荐