4

I'm currently working on a Quizzing Tool that uses hibernate and spring. I'm actually building it as a Sakai LMS tool and that complicates this question a little more, but let me see if I can generalize.

My current scenario is when users go to a StartQuiz page, which when they submit the form on the page, initializes an Attempt object(Stored by hibernate). It populates the object below:

<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>

It randomly picks out a set of questions and sets the start time and a few other properties, then redirects the user to the TakeTheQuiz page after saving the object through hibernate.

On the TakeTheQuiz page it loads the attempt object by its ID which is passed as a request param, then prints and formats it into an html form for the user to fill out the quiz. About 2/5 concurrent users will see no questions. The attempt object loads, and its questions are empty.

My theory is that the question list in the Attempt object is either not inserting immediately to the database(which is fine as long as the object goes to the hibernate cache, and I can then get it from the cache ,which I cant see to figure out how to do) OR it is saving to the Database, but my load of the object on the TakeTheQuiz page is reading an incomplete object from the cache.

Admittedly my Hibernate knowledge is limited, so if someone can help me understand what could be happening here and how to fix it, please let me know.

Chris R
  • 61
  • 5

2 Answers2

1

The answer, as I found out, was simple. It seemed that my save function was committing to the database lazily. Once I forced commits for that object at the end of each transaction the problem was solved.

I ended up writing my own hibernate session code which looks like this:

Session session = getSession();
session.beginTransaction();
session.saveOrUpdate(attempt);
session.getTransaction.commit();
session.close();

Problem solved.

Chris R
  • 61
  • 5
0

My theory is that there is something wrong with the piece of code that randomly picks the questions. Are you sure that it works? Please paste some of your code.

A second theory is that there is something wrong with your transaction boundaries. When do you flush the session? And when is your transaction committed? Give it a try and set the FlushMode on your session to ALWAYS. Does this change something?

sorencito
  • 2,517
  • 20
  • 21
  • I have put some debugging code in now that checks after the randomizer and after the attempt object has been saved, but before the redirect to the TakeTheQuiz page. The question list contains the questions after the save and before the loading on the next page. Did you still want to see the code, or does that kind of cover it? – Chris R Dec 13 '12 at 21:02
  • Ok. Anyway, i'm not sure about what your actually doing when loading the object and how the transaction boundaries look like. Did you try the FlushMode.ALWAYS? – sorencito Dec 13 '12 at 21:11
  • Further, I do not quite understand your concerns about the cache. Are you loading the Attempts via their id our using some sort of query? – sorencito Dec 13 '12 at 21:13
  • I'm loading the attempts via a findbythisId method which is a wrapper for a bunch of transactional hibernate stuff. All provided by the sakai kernel. – Chris R Dec 13 '12 at 21:26
  • Also to answer your question about FlushMode.ALWAYS, I haven't tried it, but I am explicitly flushing after saving the Attempt object. – Chris R Dec 13 '12 at 21:28
  • And after loading the Attempt object the questions are there? – sorencito Dec 13 '12 at 21:36
  • No, unfortunately after loading the attempt object on the TakeTheQuiz page the questions are sometimes not there. – Chris R Dec 17 '12 at 14:29