首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >org.hibernate.Session.clear()被认为有害吗?

org.hibernate.Session.clear()被认为有害吗?
EN

Stack Overflow用户
提问于 2011-11-14 07:20:35
回答 2查看 34.6K关注 0票数 27

这是一个设计问题,没有提交具体的代码来保护我的底部。

使用Hibernate时,标准工作流如下:

  1. 公开会议
  2. 启动事务
  3. 做生意(读取和修改数据)
  4. 提交事务
  5. 闭幕式

可能会重复2-4次。

Session.clear()的合理用例是什么?

答:我遇到的具体问题是一段(大的)代码,它加载和修改实体,然后清除()会话,实质上丢弃了所做的更改。(要完成的业务任务不包括修改实体,因此代码“工作”)。

在我看来,正确的设计应该是确保(大的)代码不做它不想保存的更改?

B:我想Session.clear()的存在是为了方便/灵活,而不是因为使用它是个好主意。

我是否误解了Hibernate的哲学?

C:子问题:当任务完成时,框架代码无条件地清除()会话是个坏主意吗?IMHO,当任务完成时,如果会话是脏的,框架应该会抱怨!当任务完成后,会议应该结束.(忽略表演一分钟)

(标签A,B和C,这样你就可以指出你回答的是哪一部分)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-14 07:38:26

广告:看起来您知道clear()是做什么的。显式调用它的原因是要从L1缓存中删除所有托管实体,以便在处理一个事务中的大型数据集时,它不会无限增长。

它放弃了对托管实体所做的所有更改,这些更改没有显式地持久化。这意味着您可以安全地修改一个实体,显式地更新它并清除会话。这是正确的设计。显然,如果不进行任何更改(长,但只读会话),clear()始终是安全的。

您也可以使用无国籍会话

广告B:不,它存在的原因如下:为了确保L1 (会话缓存)不会增长太多。当然,手动维护它是一个糟糕的想法,表明应该为大型数据集使用另一个工具,但有时它是必须的。

注意,在JPA规范中也有clear()flush()方法。在这种情况下,您应该始终先调用flush(),以便在调用clear()之前将更改推入数据库(显式更新)。

广告C:当用户使用脏的更改清除会话时,警告用户(可能是通过发出警告消息而不是抛出异常)实际上是个好主意。另外,我认为框架代码不应该无条件地调用clear(),除非它运行的用户代码会刷新或不做任何更改。

票数 30
EN

Stack Overflow用户

发布于 2015-12-27 04:07:53

我刚才遇到的另一个原因是:在同一事务中多次调用存储过程时缓存先前的结果。简化代码如下。

代码语言:javascript
复制
//Begin transaction
SessionFactory sf = HibernateSessionFactory.getFactory();
Session dbSession = sf.getCurrentSession();
dbSession.beginTransaction();

//First call to stored procedure
Query query = dbSession.getNamedQuery("RR_CUST_OPP_DATA");
query.setString("custName", "A");
List<ShipSummaryRow> shipSummaryRows = query.list();

//Second call to stored procedure
Query query = dbSession.getNamedQuery("RR_CUST_OPP_DATA");
query.setString("custName", "B");
List<ShipSummaryRow> shipSummaryRows = query.list();

//Commit both    
dbSession.getTransaction().commit();

在第一个调用之后,如果没有clear(),第一个调用的结果集行将被复制到第二个调用的结果集中。我用的是Oracle 11gR2。

复制此错误的关键是在同一个事务中进行两个调用。因为我在视图模式中使用开放会话,所以这两个调用都自动发生在同一个事务中(因为原始代码在存储每个事务的结果的循环中调用proc )。因此,我称它为bug;否则可以被认为是一种特性,但即使这样,在代码示例中也不会调用clear(),说明应该调用它。session.flush()什么也没做。映射文件如下所示。因此,我在所有过程调用的末尾添加了clear()。还没有用我的自定义SQL调用进行测试。这是一些琐碎的事情,让人惊讶的是这个bug的存在。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.jfx.rr.model.ShipSummaryRow">
        <id name="id" type="integer"/>
        <property name="shipQtrString" not-null="true" type="string"/>
        <property name="shipAmount" not-null="true" type="double"/>
    </class>
    <sql-query callable="true" name="RR_CUST_OPP_DATA">
        <return class="com.jfx.rr.model.ShipSummaryRow">
            <return-property column="SHIPPED_ID" name="id"/>
            <return-property column="SHIP_QTR" name="shipQtrString"/>
            <return-property column="SHIPPED_AMOUNT" name="shipAmount"/>
        </return>
        { call RR_DASHBOARD_REPORTS_PKG.RR_CUST_OPP_DATA(?, :custName) }
    </sql-query>
</hibernate-mapping>
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8118436

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档