我目前正在研究一种使用休眠和弹簧的测验工具。我实际上是将它构建为Sakai LMS工具,这使问题复杂化了一些,但让我看看我是否可以概括。
我目前的情况是用户访问StartQuiz页面,当他们在页面上提交表单时,初始化一个Attempt对象(由hibernate存储)。它填充下面的对象:
<class name="org.quiztool.model.Attempt" table="QT_ATTEMPTS">
<cache usage="transactional" />
<id name="id" type="long">
<generator class="native">
<param name="sequence">QT_ATTEMPTS_ID_SEQ</param>
</generator>
</id>
<many-to-one name="quizId" class="org.quiztool.model.Quiz" cascade="none" />
<property name="score" type="int" not-null="true" />
<property name="outOf" type="int" not-null="true" />
<list name="responses" cascade="none" table="QT_RESPONSES" lazy="false">
<key column="id"/>
<index column="idxr"/>
<many-to-many class="org.quiztool.model.QuizAnswer" />
</list>
<list name="questionList" cascade="none" table="QT_ATTEMPT_QUESTIONS" lazy="false">
<key column="id"/>
<index column="idxq"/>
<many-to-many class="org.quiztool.model.QuizQuestion" />
</list>
<property name="userId" type="string" length="99" />
<property name="siteRole" type="string" length="99" />
<property name="startTime" type="java.util.Date" not-null="true" />
<property name="finishTime" type="java.util.Date" />
</class>
随机选择一组问题并设置开始时间和其他一些属性,然后在通过休眠保存对象后将用户重定向到TakeTheQuiz页面。
在TakeTheQuiz页面上,它通过作为请求参数传递的ID加载尝试对象,然后将其打印并格式化为html表单,供用户填写测验。大约2/5并发用户将看不到任何问题。加载尝试对象,其问题为空。
我的理论是,Attempt对象中的问题列表要么不立即插入数据库(只要对象进入hibernate缓存就可以了,然后我可以从缓存中获取它,我不能看看如何做)或者它保存到数据库,但我在TakeTheQuiz页面上的对象加载是从缓存中读取一个不完整的对象。
不可否认,我的Hibernate知识是有限的,所以如果有人可以帮助我理解这里可能发生的事情以及如何解决它,请告诉我。
答案 0 :(得分:1)
我发现答案很简单。似乎我的保存功能懒惰地提交到数据库。一旦我在每次交易结束时强制提交该对象,问题就解决了。
我最终编写了自己的hibernate会话代码,如下所示:
Session session = getSession();
session.beginTransaction();
session.saveOrUpdate(attempt);
session.getTransaction.commit();
session.close();
问题解决了。
答案 1 :(得分:0)
我的理论是随机选择问题的代码片段有问题。你确定它有效吗?请粘贴一些代码。
第二个理论是您的交易边界存在问题。什么时候刷新会话?您的交易何时提交?试一试,将会话中的FlushMode设置为ALWAYS。这会改变什么吗?