My problem: A criteria gets me an object. I delete it and add another. Later I run the same criteria and it retreives the object I thought I deleted earlier. Further, the criteria does not return the added object even though it would qualify for the results. All code uses the same session object and as far as I can tell the transaction has remained open throughout these operations.
I think the session should remember that I deleted the object and should not return it in the results of any future criteria built from that session. Further, it should return the newly added object, since it qualifies.
When the transaction commits I get erroneous results because of what the criteria saw in the seesion. For example consider the following actions on WidgetCache objects.
pk=45 (pre-exists in DB at session start)
delete pk=45
insert pk=70
delete pk=45* (incorrect, criteria should have found and deleted pk=70)
insert pk= 90
After the transaction commits, the table contains both pk=70 and pk=90. I want it to contain only pk=90. If the criteria returned the correct results, all would be fine, I think.
So, maybe I'm abusing the session, or have got something misconfigured, but after spending a couple of hours reading the docs and poking around this app (which I did not write, but must maintain) I cannot find an explanation for the behavior. The configuration object is pretty standard and does not have a lot of customizations.
If anyone has some ideas, I'd love to hear them.
Here is the simplified (although not much) code for the criteria, delete, and insert.
Code:
public void updateWidgetCache (Session session Widget theWidget) {
Criteria crit = session.createCriteria (WidgetCache.class);
crit.add (<some_expression> );
List currentIssueList = crit.list ();
WidgetCache wc = getWidgetInCache(currentIssueList , theWidget);
if (wc ! null) {
session.delete(wc);
WidgetCache.create(session, theWidget);
} else {
WidgetCache.create(session, theWidget);
}
}
[in WidgetCache.java]
public WidgetCache create (Session session, Widget theWidget) {
WidgetCache wc = new WidgetCache();
copySomeAttributes(theWidget, wc);
session.save(wc);
return wc;
}
Our sessions are obtained from the factory like this:
Session session = factory.openSession();
session.setFlushMode(FlushMode.COMMIT);
return session;
Here is how the Configuration object is set up:
Configuration cfg = new Configuration();
cfg.setProperty("hibernate.connection.driver_class", driver);
cfg.setProperty("hibernate.connection.url", url);
cfg.setProperty("hibernate.connection.username", username);
cfg.setProperty("hibernate.connection.password", password);
cfg.setProperty("hibernate.c3p0.min_size", "5");
cfg.setProperty("hibernate.c3p0.max_size", "20");
cfg.setProperty("hibernate.c3p0.timeout", "1800");
cfg.setProperty("hibernate.c3p0.max_statements", "50");
cfg.setProperty("hibernate.dialect", dialect);
cfg.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.HashtableCacheProvider");
cfg.addResource("app.hbm.xml");
factory = cfg.buildSessionFactory();
Hibernate version: 3.0.2
Name and version of the database you are using: MySQL 4.1.12