这是一个设计问题,没有提交具体的代码来保护我的底部。
使用Hibernate时,标准工作流如下:
可能会重复2-4次。
Session.clear()的合理用例是什么?
答:我遇到的具体问题是一段(大的)代码,它加载和修改实体,然后清除()会话,实质上丢弃了所做的更改。(要完成的业务任务不包括修改实体,因此代码“工作”)。
在我看来,正确的设计应该是确保(大的)代码不做它不想保存的更改?
B:我想Session.clear()的存在是为了方便/灵活,而不是因为使用它是个好主意。
我是否误解了Hibernate的哲学?
C:子问题:当任务完成时,框架代码无条件地清除()会话是个坏主意吗?IMHO,当任务完成时,如果会话是脏的,框架应该会抱怨!当任务完成后,会议应该结束.(忽略表演一分钟)
(标签A,B和C,这样你就可以指出你回答的是哪一部分)。
发布于 2011-11-14 07:38:26
广告:看起来您知道clear()是做什么的。显式调用它的原因是要从L1缓存中删除所有托管实体,以便在处理一个事务中的大型数据集时,它不会无限增长。
它放弃了对托管实体所做的所有更改,这些更改没有显式地持久化。这意味着您可以安全地修改一个实体,显式地更新它并清除会话。这是正确的设计。显然,如果不进行任何更改(长,但只读会话),clear()始终是安全的。
您也可以使用无国籍会话。
广告B:不,它存在的原因如下:为了确保L1 (会话缓存)不会增长太多。当然,手动维护它是一个糟糕的想法,表明应该为大型数据集使用另一个工具,但有时它是必须的。
注意,在JPA规范中也有clear()和flush()方法。在这种情况下,您应该始终先调用flush(),以便在调用clear()之前将更改推入数据库(显式更新)。
广告C:当用户使用脏的更改清除会话时,警告用户(可能是通过发出警告消息而不是抛出异常)实际上是个好主意。另外,我认为框架代码不应该无条件地调用clear(),除非它运行的用户代码会刷新或不做任何更改。
发布于 2015-12-27 04:07:53
我刚才遇到的另一个原因是:在同一事务中多次调用存储过程时缓存先前的结果。简化代码如下。
//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的存在。
<?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>https://stackoverflow.com/questions/8118436
复制相似问题