Issue Details (XML | Word | Printable)

Key: HHH-2130
Type: Improvement Improvement
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Steve Ebersole
Reporter: Frank Tolstrup
Votes: 0
Watchers: 2
Operations

If you were logged in you would be able to see more operations.
Hibernate Core

SQLQuery does not autoflush all entities used in the query

Created: 04/Oct/06 06:05 AM   Updated: 17/Nov/06 10:21 PM
Component/s: core, query-sql
Affects Version/s: 3.1.3
Fix Version/s: 3.2.2

Time Tracking:
Not Specified

Environment: Hibernate version 3.1.3, Oracle v 9.2


 Description  « Hide
I have a problem with autoflushing on native SQL queries. The scenario is:

1. I use a complex sql with a lot of joined tables
2. I change some of the associated objects from the result (but not the returned types).
3. I do the same sql as in step 1

The problem is that the autoflush before the sql in step 3 only flushes changes in objects of the class returned by the sql, NOT all other objects used in the query.

If I change the query in step 3 to HQL it works as I would expect and flushes all objects included in the query.

It says in the hibernate documentation (section 10.10 Flushing the session), that

"However, Hibernate does guarantee that the Query.list(..) will never return stale data; nor will they return the wrong data."

This seems not to be the case with native SQL queries.

The SQL query: (flushes only changed Tjeneste objects)
SQLQuery sqlQuery = session.createSQLQuery
("SELECT /*+ use_nl(a av) */ {t.*}"
+"FROM TJENESTE t, "
+"TJENESTEVERSION tv, "
+"ALLOKERING a, "
+"ALLOKERINGSVERSION av "
+"WHERE t.TJENESTE_ID = tv.TJENESTE_ID "
+"AND av.plan_id = 0 "
+"AND av.slettet = 0 "
+"AND av.allokering_id = a.allokering_id "
+"AND a.medarbejder_id =:medarb "
+"AND tv.tjeneste_id = av.tjeneste_id "
+"AND tv.fra_tid >= :fraTid "
+"AND tv.til_tid <= :tilTid"
);

The HQL query: (flushes changed objects of classes Tjeneste, TjenesteVersion, AllokeringsVersion, Allokering)

("SELECT av.tjeneste "
+" FROM"
+" TjenesteVersion tv,"
+" AllokeringsVersion av"
+" WHERE "
+" av.plan.id = 0"
+" and av.slettet = 0"
+" and av.allokering.medarbejder.id = :medarb"
+" and tv.tjeneste = av.tjeneste"
+" and tv.plan.id = 0"
+" and tv.fraTid >= :fraTid"
+" and tv.tilTid <= :tilTid"

It would be enough to add a method to SQLQuery to add entities to the QuerySpace that will be flushed before the query is executed. An api method to match the "<synchronize>" in a named query.

Regards,
Frank


PS: See the thread in the Hibernate user forum:
        http://forum.hibernate.org/viewtopic.php?p=2324846

 All   Comments   Work Log   Change History   FishEye      Sort Order: Ascending order - Click to sort in descending order
Christian Bauer added a comment - 04/Oct/06 06:10 AM
Changed to minor improvement. Obviously Hibernate doesn't know what you do in your SQL query, so you have to call flush().

Timm Kristensen added a comment - 04/Oct/06 06:53 AM
Im not sure that i agree that this a minor improvement, since it says in the documentation :

"However, Hibernate does guarantee that the Query.list(..) will never return stale data; nor will they return the wrong data."

This it obviously dos not guarantee. Yes you could just call flush, but this will make hibernate flush the whole session, not just the data needed for the query, wich might be a bit inefficient.

Anyway
Maybe you could add the possibility of adding querySpaces to the query. So that you can tell hibernate wich tables to flush in addition to the table of the result type.

I would suggest something like the following in org.hibernate.impl.SQLQueryImpl

 /**
     * adds a table to be dirty checked and possibly flushed
     */
    public SQLQuery addQuerySpace(String space) {
        if(querySpaces == null){
            querySpaces = new ArrayList();
        }
        querySpaces.add(space.toUpperCase());
        return this;
    }[

This makes hibernate check for, and flush, the spaces added.
I do not know if this breaks code other places in hibernate, but i do know that it fixes the problem statet by Frank. And it seems to work since i am able to run all my projects test with this addition to hibernate.

Max Rydahl Andersen added a comment - 04/Oct/06 07:57 AM
it is still only an improvement and the doc for SQLQuery(!) documents synchronize and the need for it. (it is the same if you disable flushing then hibernate can also not guarantee that it will never return stale data)


Timm Kristensen added a comment - 04/Oct/06 08:35 AM
Could you possibly provide me with a link to the documentation that you mention ? i do not seem to be able to find it.

Yes, i am fully aware that hibernate cant guarentee data consistency if the data is not flushed, hence the problem.

As it is now its not possible for hibernate, and the user, to flush the affected tables, unless you flush the whole session. The solution i propose is a small feature, which would make it possible for the user to declare which tables are used and hence which tables hibernate need to check for dirty data.

Max Rydahl Andersen added a comment - 04/Oct/06 09:40 AM
It *is* possible, ust used namedquery - for the programmatic api it is not, hence its an improvement.

Regarding the documenation, search for <synchronize>. (p.s. the native sql docs could probably be more explicit about synchronize)

Steve Ebersole added a comment - 16/Nov/06 10:19 AM
Yes, such functionality should be added to the SQLQuery interface. Something like SQLQuery.addSynchronize(String)...

Steve Ebersole added a comment - 17/Nov/06 10:21 PM
trunk / 3.2