热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

Hibernate提供的操作数据库的方法使用和比较

hibernate对于对象的操作提供了很多的方法,本文简单介绍一下这些方法的使用和比较.在说明方法之前,说明一下hibernate中的对象的三

hibernate对于对象的操作提供了很多的方法,本文简单介绍一下这些方法的使用和比较.在说明方法之前,说明一下hibernate中的对象的三

hibernate对于对象的操作提供了很多的方法,本文简单介绍一下这些方法的使用和比较.

在说明方法之前,说明一下hibernate中的对象的三种状态,transient,persistent,detached.
transient:瞬态或者自由态.
persistent:持久化状态.
detached:脱管状态或者游离态.

状态的判断:

大体上来说,存在于session中的对象为persistent,从session中被clear,evict出来的对象(包括commit是被移出来的对象)是detached.新建的对象和delete的对象是transient状态.但是一个新建的对象的如果有version字段,并且version字段unsaved-value不同,或者在id在由代码赋值的时候有值,则认为是detached状态.

1,persist和save方法:

按照spec,persist不保证立即执行SQL insert语句,save会立即执行insert语句.

在使用过程中,如果记录的id不配置为由代码赋值,如果不为 ,如果对transient或者detached对象的oid赋上值,调用persist方法会有异常:

org.hibernate.PersistentObjectException: detached entity passed to persist:

如果用save方法的话,能够保存成功,赋的oid值不起作用.

如果想要赋的值起作用,用save(Object,ID)的方法.可以用replicate方法做类似的操作.

2,saveOrupdate不是根据数据库有无记录来做save或者update,而是根据对象的状态,如果为transient对象,则save,如果是detached状态,则update.总是会触发hibernate session的save或者update.例如:如果记录的oid不配置为由代码赋值,如果不为 ,如果对这个对象的oid赋了值,Hibernate总是发出一条SQL Update语句,如果数据库没有该oid对应的记录,就不会更新任何记录,如果oid的值为空 的话,会进行save.

如果记录的oid配置为由代码赋值 , ,如果对应该oid的记录不存在 ,就save,如果存在就update.在代码中必须为oid赋值,否则会有异常:org.hibernate.id.IdentifierGenerationException:ids for this class must be manually assigned before calling save():

在同一个session中,对一个transient对象进行saveOrupdate,如果这个对象的oid正好和session中已经存在的对象oid相同,不论对id赋值配置为何种机制,这是候会有异常:

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:

(上面这条规则同样适用于update方法)

与update的区别是update总是根据对象的oid去update,对于update方法,如果没有设oid会有异常:

org.hibernate.TransientObjectException: The given object has a null identifier:

在一个session中,对delete的obj进行update会有异常,如:

session.delete(obj);

....

session.update(obj);

但是对另一个session中(或者其他程序)delete的对象可以进行update,只是对数据库没有任何改动.

3,merge与update和saveorupdate的区别:从运行是看,最明显的区别是如果update或者saveOrupdae的对象的oid和session中的某个对象相同,会有异常抛出,而merge不会.

如果merge的对象在数据库不存在,会save一条记录(和saveOrupdate类似).

如果session中存在相同oid的实例,会用merge的对象的状态覆盖旧有的持久实例.

Hbtest tbo = new Hbtest();
tbo.setId(new Integer(100));
tbo.setVal("val3");
sessionFactory.getCurrentSession().save(tbo);

Hbtest tbo1 = new Hbtest();
tbo1.setId(new Integer(100));
tbo1.setVal("val5");
sessionFactory.getCurrentSession().merge(tbo1); //update database

System.out.println("******* merge *******" + tbo.getVal()); //tbo的值为val5

如果session没有相应的持久实例,则尝试从数据库中加载或创建一个新的持久化实例,merge方法会返回该持久实例
刚刚merge的这个对象没有被关联到session上,它依旧是游离态的.如果在merge后,对其做改变,值不会反映到数据库.

Hbtest tbo1 = new Hbtest();

sessionFactory.getCurrentSession().merge(tbo1);

...

tbo1.setVal("new val");//不会更新到数据库.

对返回的对象的改动会相应的更新数据库

Hbtest tbo2 = (Hbtest)sessionFactory.getCurrentSession().merge(tbo1);

tbo2.setVal("new val");

merge的作用和数据库提供的merge类似,如Oracle的merge into语句.

可以看出,只有在session中已经存在一个具有相同标识符的持久对象的时候,应该采用merge,此时用saveOrUpdate或者update会报错.如果不确定当前session中是否已经有了具有相同标识符的持久对象,又想将当前的对象更新到(save 或者update)数据库中,可以用merge.

4,replicate()方法完全使用给定对象各个属性的值(包括oid)来持久化给定的游离状态的实体,其中还需要指定存储模式.replicate会先用select看数据是否在数据库已经存在,如果存在,就update,否则save(在存储模式为LATEST_VERSION或者OVERWRITE时).

与save的区别:如果id已经存在,save会有异常(主键冲突,org.hibernate.exception.ConstraintViolationException),在不是由代码指定主键的时候,给save的对象赋的oid不会起作用,而由hibernate配置的机制负责.而replicate会用赋值的oid对数据库进行操作.

与update的区别:比update多执行一条select语句.

在实际应用中用在,如果想把一个数据库中的记录复制到另一个数据库中,可以用replicate方法,通过ReplicationMode来控制当数据冲突是的行为.

5,delete和evict

evict,从session的缓存中去除当前实例.执行后对象的改变将不再和数据库保持同步.当指定级联风格为evict时,会级联操作关联对象.在用于批量操作的时候,清空缓存,防止内存紧张.
delete,也会从session的缓存中去除当前实例,但flunsh时会执行数据库delete,之后对象就成了临时状态.

delete之后的对象不能调用update和merge方法,但是可以运用saveOrUpdate方法.
可以看出delete比起evict,不仅从session删除,还会从数据库删除.

6,load和get

如果找不到符合条件的纪录,get()方法将返回null.而load()将会报出ObjectNotFoundEcception.如果你使用 load方法,hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的,所以它可以放心的使用,它可以放心的使用代理来延迟加载该对象。在用到对象中的其他属性数据时才查询数据库,但是万一数据库中不存在该记录,那没办法,只能抛异常,所说的load方法抛异常是指在使用该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时。由于 session中的缓存对于hibernate来说是个相当廉价的资源,所以在load时会先查一下session缓存看看该id对应的对象是否存在,不存在则创建代理,实际使用数据时才查询二级缓存和数据库.所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载。

load()方法可以返回实体的代理类实例,而get返回的可能是实体类,也可能是代理类.get方法如果在session缓存中找到了该id 对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象,如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。

7,query的list和iterate方法:list会一次取数据,iterate会先取id,再根据id多次取数据. refer

8,Session的clear,evict和flush方法
clear()方法清除Session级别缓存中的所有实体(包括各种状态)对象,,目的是释放内存.
evict()方法清除Session级别缓存中的指定的实体(包括各种状态)对象.
flush()强制持久化Session缓存中的实体对象,不会从缓存中清除对象.

sessionFactory.getCurrentSession().save(tbo1);

sessionFactory.getCurrentSession().flush();//执行SQL,如果在clear之前不执行flush,tbo1不会被保存到数据库

sessionFactory.getCurrentSession().clear();

sessionFactory.getCurrentSession().save(tbo1);
sessionFactory.getCurrentSession().flush();
sessionFactory.getCurrentSession().evict(tbo1); //如果在evict之前不执行flush,会有异常.


推荐阅读
  • 本文介绍了如何在MySQL中将零值替换为先前的非零值的方法,包括使用内联查询和更新查询。同时还提供了选择正确值的方法。 ... [详细]
  • 本文介绍了如何使用Power Design(PD)和SQL Server进行数据库反向工程的方法。通过创建数据源、选择要反向工程的数据表,PD可以生成物理模型,进而生成所需的概念模型。该方法适用于SQL Server数据库,对于其他数据库是否适用尚不确定。详细步骤和操作说明可参考本文内容。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • MyBatis错题分析解析及注意事项
    本文对MyBatis的错题进行了分析和解析,同时介绍了使用MyBatis时需要注意的一些事项,如resultMap的使用、SqlSession和SqlSessionFactory的获取方式、动态SQL中的else元素和when元素的使用、resource属性和url属性的配置方式、typeAliases的使用方法等。同时还指出了在属性名与查询字段名不一致时需要使用resultMap进行结果映射,而不能使用resultType。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了通过mysql命令查看mysql的安装路径的方法,提供了相应的sql语句,并希望对读者有参考价值。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
author-avatar
yangdawen1985_156
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有