记录一下hibernate使用saveOrUpdate()出现异常。

10 篇文章 0 订阅

最近在对一个很老的项目进行二次开发其中使用到了比较老的框架(hibernate)

问题描述

在一个拦截器中实现日志记录功能。日志记录时候会连带更新其他表操作。(即插入日志时候会连带更新其他实体表)

问题解析

当save(Object)的时候分3种情况:

 一,当object是临时状态的时候:

  ①当id策略为native的时候,当执行save的时候会向数据库发一条insert 语句,并获取id。

②当id为aasiged的时候,save的时候仅仅会持久化,然后commit的时候发出一条Insert 语句。

二,当object是游离对象的时候:

①当id策略为native的时候,当执行save的时候,数据库依然后发出一条insert语句,此时该游离对象的Id被改变了!

②当Id策略为assiged的时候,当执行save的时候,依然还是发出一条inser语句,此时数据库报错,违反唯一约束。

三,当object为持久化对象的时候:

不管id为何种策略,当执行save的时候,不会有任何操作。

总结save()的用法:不管传入的对象是什么状态,都会当作临时对象进行操作(持久化状态就直接返回)。

当update()的时候:

其实处理机制与save差不多,当传入对象是持久化对象的时候,如果持久化没有改变的话,就不会发出Update语句;当传入的是临时和游离状态的对象的时候,

update()都会当作游离对象处理,如果该临时对象没有id值,那么update(object)的时候会理解报错,错误为:org.hibernate.id.IdentifierGenerationException(id策略为assiged),

或者org.hibernate.TransientObjectException(id策略为native),如果该临时对象有带Id,此时该对象会被当作游离对象处理,清理缓存的时候,会向sql发出一条update语句。

这样从save与update,游离对象与临时对象没什么大的区别,只要临时对象有带id值,就完全可以当作游离对象处理!!!

当执行saveOrUpdate()的时候:

当传入对象是持久化对象的时候,执行saveOrUpdate()的操作,直接返回,不会执行什么内容!

下面分两种情况:

一,当传入的对象是游离对象的时候:

①id为native策略:当执行saveOrUpdate(),这个时候会发出如下语句:

Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into t_user (name, id) values (?, ?)
Hibernate: update t_user set name=? where id=?

②当id为assiged策略:当执行saveOrUpdate()的时候会发出如下语句:

Hibernate: insert into t_user (name, id) values (?, ?)
Hibernate: select user2x_.id, user2x_.name as name0_ from t_user user2x_ where user2x_.id=?

上面可以看出saveOrUpdate()会先判断对象是否是游离状态还是临时状态,当id为natice策略的时候,很容易就能判断出对象是否是游离对象,但是当id为assiged策略的是时候,就判断不出对象是否是临时的还是游离的,因为assiged下,id都不为null,因此会发出select 语句查出数据库是否有记录来判断是否是游离状态,如果发现是游离状态,就什么也不干,也不会执行save()即insert操作!

二,当传入对象为临时对象的时候:

①id为native策略:当执行saveOrUpdate(),这个时候会发出如下语句:

Hibernate: insert into t_user (name, id) values (?, ?)

②当id为assiged策略:当执行saveOrUpdate()的时候会发出如下语句:

Hibernate: select user2x_.id, user2x_.name as name0_ from t_user user2x_ where user2x_.id=?

Hibernate: insert into t_user (name, id) values (?, ?)

即会查找数据库是否存在该记录,如果有即为游离状态,就会对比该游离对象的属性是否与数据库一致,如果一致就不发update语句,如果不一致,那么就发出update改变某字段的update语句。,如果没,即是确定为临时状态,就执行save操作!!!

总结:在id为native,和assiged,当对象为游离对象的时候,两者情况下,执行的结果不一样,在assiged的条件下,不会有Update操作!,而native的时候,会发出update操作!
重上述解析可以了解连带更新操作是因为数据Session 中含有其他游离对象导致插入日志时候同时更新其他表

所以解决方案是

session.clear()清空Session 缓存可以解决该问题

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值