`

hibernate点滴记录

阅读更多
一、fetch="join" 和 fetch="select" 没区别?

fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查询;
而join方式,主体对象和关联对象用一句外键关联的sql同时查询出来,不会形成多次查询。
如果你的关联对象是延迟加载的,它当然不会去查询关联对象。
另外,在hql查询中配置文件中设置的join方式是不起作用的(而在所有其他查询方式如get、criteria或再关联获取等等都是有效的),会使用select方式,除非你在hql中指定join fetch某个关联对象。
二、重新学习 Hibernate fetch lazy cascade inverse 关键字
(1)、延迟加载,默认 lazy="true"。
(2)、fetch 和 lazy 主要是用来级联查询的,而 cascade 和 inverse 主要是用来级联插入和修改的。
(3)、如果你是用spring来帮你管理你的session, 并且是自动提交,延迟加载就等于没加载(当然除非你手动重新打开session然后手动Hibernate.initialize(set);然后关闭session。
(4)、cascade主要是简化了在代码中的级联更新和删除。
在网上找到一个例子感觉还可以:
老爸可以有多个孩子,一个孩子不能有多个老爸,而且老爸说的算, 孩子围着老爸转。所以Photos老爸要有权力所以 cascade 这个关键子都是送给老爸的, 也就是级联更新,老爸改姓了,儿子也得跟着改,呵呵。“不然,就没有零花钱咯”。而Picture儿子整体挨骂,但是还是要维护父子之间良好的关系,对老爸百依百顺,所以老爸就说,儿子,“关系,由你来维护(inverse="true") ,不然就不给零花钱。呵。”。
<set name="pictures" inverse="true" cascade="all">
     <key>
<column name="photosid" not-null="true" />
     </key>
     <one-to-many class="girl.domain.Picture" />
</set>

三、hibernate中po对象的三种状态分析
hibernate的各种保存方式的区(save,persist,update,saveOrUpdte,merge,flush,lock)及 对象的三种状态
hibernate的保存
hibernate对于对象的保存提供了太多的方法,他们之间有很多不同,这里细说一下,以便区别。
一、预备知识
在所有之前,说明一下,对于hibernate,它的对象有三种状态,transient、persistent、detached
下边是常见的翻译办法:
transient:瞬态或者自由态
(new DeptPo(1,”行政部”,20,”行政相关”),该po的实例和session没有关联,该po的实例处于transient)
persistent:持久化状态
(和数据库中记录想影射的Po实例,它的状态是persistent, 通过get和load等得到的对象都是persistent)
detached:脱管状态或者游离态
    (1)当通过get或load方法得到的po对象它们都处于persistent,但如果执行delete(po)时(但不能执行事务),该po状态就处于detached, (表示和session脱离关联),因delete而变成游离态可以通过save或saveOrUpdate()变成持久态
(2)当把session关闭时,session缓存中的persistent的po对象也变成detached
因关闭session而变成游离态的可以通过lock、save、update变成持久态
持久态实例可以通过调用 delete()变成脱管状态。
通过get()或load()方法得到的实例都是持久化状态的。
脱管状态的实例可以通过调用lock()或者replicate()进行持久化。

save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,
而update()或merge()会引发SQL UPDATE。对持久化(persistent)实例的修改在刷新提交的时候会被检测到,它也会引起SQL UPDATE。
saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE
二、save 和update区别
把这一对放在第一位的原因是因为这一对是最常用的。
save的作用是把一个新的对象保存
update是把一个脱管状态的对象或自由态对象(一定要和一个记录对应)更新到数据库

三、update 和saveOrUpdate区别
这个是比较好理解的,顾名思义,saveOrUpdate基本上就是合成了save和update,而update只是update;引用hibernate reference中的一段话来解释他们的使用场合和区别
通常下面的场景会使用update()或saveOrUpdate():
程序在第一个session中加载对象,接着把session关闭
该对象被传递到表现层
对象发生了一些改动
该对象被返回到业务逻辑层最终到持久层
程序创建第二session调用第二个session的update()方法持久这些改动

saveOrUpdate(po)做下面的事:
如果该po对象已经在本session中持久化了,在本session中执行saveOrUpdate不做任何事
如果savaOrUpdate(新po)与另一个与本session关联的po对象拥有相同的持久化标识(identifier),抛出一个异常
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [org.itfuture.www.po.Xtyhb#5]
saveOrUpdate如果对象没有持久化标识(identifier)属性,对其调用save() ,否则update() 这个对象

四、persist和save区别
这个是最迷离的一对,表面上看起来使用哪个都行,在hibernate reference文档中也没有明确的区分他们.
这里给出一个明确的区分。(可以跟进src看一下,虽然实现步骤类似,但是还是有细微的差别)
主要内容区别:
1,persist把一个瞬态的实例持久化,但是并"不保证"标识符(identifier主键对应的属性)被立刻填入到持久化实例中,标识符的填入可能被推迟到flush的时候。

2,save, 把一个瞬态的实例持久化标识符,及时的产生,它要返回标识符,所以它会立即执行Sql insert

五、saveOrUpdate,merge和update区别
比较update和merge
update的作用上边说了,这里说一下merge的
如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象覆盖session已有的持久实例
(1)当我们使用update的时候,执行完成后,会抛出异常
(2)但当我们使用merge的时候,把处理自由态的po对象A的属性copy到session当中处于持久态的po的属性中,执行完成后原来是持久状态还是持久态,而我们提供的A还是自由态

六、flush和update区别
这两个的区别好理解
update操作的是在自由态或脱管状态(因session的关闭而处于脱管状态)的对象//updateSQL
而flush是操作的在持久状态的对象。
默认情况下,一个持久状态的对象的改动(包含set容器)是不需要update的,只要你更改了对象的值,等待hibernate flush就自动更新或保存到数据库了。hibernate flush发生在以下几种情况中:
1, 调用某些查询的和手动flush(),session的关闭、SessionFactory关闭结合
get()一个对象,把对象的属性进行改变,把资源关闭。
2,transaction commit的时候(包含了flush)

七、lock和update区别
update是把一个已经更改过的脱管状态的对象变成持久状态
lock是把一个没有更改过的脱管状态的对象变成持久状态(针对的是因Session的关闭而处于脱管状态的po对象(2),不能针对因delete而处于脱管状态的po对象)
对应更改一个记录的内容,两个的操作不同:
update的操作步骤是:
(1)属性改动后的脱管的对象的修改->调用update
lock的操作步骤是:
(2)调用lock把未修改的对象从脱管状态变成持久状态-->更改持久状态的对象的内容-->等待flush或者手动flush
八、clear和evcit的区别
  clear完整的清除session缓存
  evcit(obj)把某个持久化对象从session的缓存中清空。
session.lock(xtyhb,LockMode.NONE);//表示直接到缓存中去找变成持久态的对象
session.lock(xtyhb,LockMode.READ);//先通过ID读数据库该记录的ID看是否有该记录,如果有接着到缓存中去找变成持久态的对象


1)写入和查询语句不执行。
      写了个简单的session.save(obj)语句,你却发现它并不执行。原来是因为数据库表是事务表,所以,需要把这个语句放到事务里面执行。这个还好说。
      过了不久,你发现query查询居然没有执行!你把hibernate生成的sql语句放到数据库客户端执行,明明有好些结果,可是,hibernate愣是不给你出结果!它也不是老不出,一段时间之后,它就执行了,会给你一个结果。查询语句居然不是实时的...... 在google了很长时间之后(半天),才看到一个说法:把查询语句用事务封装起来。于是这么做了,于是就发现hibernate能够马上执行查询语句了。

2)执行本地SQL语句返回结果奇特。
      数据库中有几个表,需要进行左连接访问(left join),用sql语句很容易做到。可是,当你打算用hql语句来做到这点的时候,你就蒙了。你发现配置那个麻烦啊,没有直接写sql语句简单。所以,你就直接写sql语句了,期待着hibernate能够像普通的jdbc那样,返回一个正确的结果。然而,看到返回的结果,你傻眼了。为什么?
     数据库表里面有一个字段类型char(4),里面的值都是“good”,可是,hibernate查询回来的居然只有一个字符:“g”。只好查看hibernate的ref里面的Native Sql那章了,看到有如下的例子:
sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
.addScalar("NAME", Hibernate.STRING)
.addScalar("BIRTHDATE", Hibernate.DATE)
     你才知道,你需要使用addScalar方法来指定某个返回字段的类型!注意的是,方法里面的第一个参数是返回字段的名称。哦,你恍然大悟。立马这样修改了自己的代码,慢着,你突然发现居然只返回了你使用addScalar指定了类型的几个字段!原来,hibernate就是这样处理的,你要返回的每个字段都必须使用addScalar指定!

3)无法简单执行基本函数。
     很多时候,我们都有一个需求:得到数据库服务器的当前时间。这是因为本机时间和服务器时间是有差别的。各种数据库都提供了函数来获得,比如,mysql,可以用“select now()”。hibernate也提供了一个函数current_timestamp(说起timestamp,个人认为数据库的timestamp做的很差,它居然和datetime是一个数量级的(精确度),这怎么可以用来表示真正的stamp啊!)。可是,你却无法用直接使用“select current_timestamp()”来获得服务器的当前时间,你还必须加上一个查询的表!比如,“select current_timestamp() from tbl_Good”。个人十分郁闷,我只是想用这个简单功能而已,为什么我一定要知道数据库里面的表格呢????更何况还必须建立映射。。。。。。

不是我不明白,这世界太复杂了 。每样产品都是拼命的复杂化,其实,它们实在是忽略了一般的用户只需要一小部分功能而已。默认的功能应该是能够满足普通用户的常见需求的,那样才算是一个好的产品。我不认为hibernate做到了这点。

4)写入数据库字符串乱码。
    简单的数据库,简单的表格,简单的字段,是字符串类型,utf-8编码。用hibernate写入正常文本,写进去就变成乱码了。显然是编码不一致的问题。hibernate里面居然没有说明如何配置。好在网络上有人说可以在hibernate的配置文件里面加上一句配置:
        <property name="connection.characterEncoding">UTF-8</property>
    这句配置并不是给hibernate用的,它会传递给底层的jdbc。告诉jdbc字符串是utf-8的编码。可能有的数据库会需要你再配置一个(以上配置mysql可以):
        <property name="connection.useUnicode">true</property>
    或许这个不应该怪hibernate,因为字符串乱码的事情是一个到处都有的问题。
分享到:
评论

相关推荐

    struts2+spring+hibernate整合的时间轴网站

    这是一个由struts2+spring+hibernate整合的时间轴网站,可以用来当作个人的日记本吧,如果你有女朋友的话,你也可以通过使用该网站,记录你们每天的生活点滴,然后你把它发给你的女朋友,那么她肯定开心死了,没有女...

    java文集

    struts通用Exception处理 Grails中默认数据库HSQLDB点滴 从request获取各种路径总结 DIV实现的表格自动伸张与收缩 java 邮件服务 从Hibernate的映射谈编程思想 COBOL 式死亡,Java 是否真的...

    SQL点滴系列之插入数据(四)

    在分析 SQL 时,也会同时分析 mybatis 、Hibernate 中的相关操作 点击查看详情 本节讲述 在数据库中插入数据 1 插入新的记录 向表中插入一条新的记录。 例如 向用户表中添加一条新的数据,可以这样写 insert into t_...

    SQL点滴系列之删除数据(五)

    在分析 SQL 时,也会同时分析 mybatis 、Hibernate 中的相关操作 点击查看详情 本节讲述 在数据库中删除表中的数据,以及 having 与 where 的分析 1 删除表中所有的记录 实际开发中,我们有时需要删除一个表中的所有...

    2022年java试用期转正工作总结500字.docx

    在学习过程中,开发者通过撰写博客记录了点滴进步,这既是自我提升的方式,也是分享和交流的平台,有助于形成良好的学习习惯和知识传承。 总结来说,这份Java试用期转正工作总结展现了开发者在项目实践中不断学习和...

    Nxjnic基于J2EE框架的个人博客系统项目毕业设计论文.doc

    博客系统不仅允许用户记录生活点滴,分享观点,还能够通过社交网络连接志同道合的朋友,甚至在某些领域内,博客已经成为专业信息的重要来源。随着博客用户的增长,对这类系统的功能需求也在不断增加,比如用户注册、...

    孙宇syutils

    孙宇的jsutils,包含一些常用的js的工具。

    典型的应用系统实例代码

    自动点滴管理系统利用.NET 3.5框架的WCF(Windows Communication Foundation)技术,这是一种服务导向架构,用于构建高度可互操作的服务,可用于企业级的数据同步和自动化任务。 基于ASP.NET的工作流批核系统使用了...

    Java 日记本系统

    Java Web日记本系统是一个基于Java技术栈开发的在线应用程序,旨在提供一个方便、安全的平台,让用户可以记录、管理和分享他们的日常生活点滴。在这个系统中,用户可以创建、编辑、删除日记条目,并可能包含一些额外...

    Yrf-Blog:我的博客

    博客平台通常用于分享技术文章、个人见解或者生活点滴,而“Yrf-Blog”很可能是博主的自定义化实现,具有个性化的功能和设计。 【描述】中的“Yrf-Blog”与标题相呼应,再次确认这是一个博客项目,但描述较为简洁,...

Global site tag (gtag.js) - Google Analytics