0

In our (ancient) project, we use loads of select queries with HQL on Hibernate version 3.5.6-Final. Because Hibernate will do an auto-commit, because it doesn't know they are select queries, I'm in the process of rewriting all HQL select queries to Hibernate Criteria queries so it won't do in-between commits when we don't want it yet. This is pretty straight-forward in most cases, but I'm currently looking at a query like this, and I'm not sure how to transform it:

Query query = session.createQuery("select municapilityStreet"
  + " from MunicapilityStreet munStreet, Street street"
  + " where munStreet.id = street.MunicapilityStreet.id"
  + " and street.id = :streetId");
query.setParameter(":streetId", streetId);
MunicapilityStreet result = (MunicapilityStreet) query.uniqueResult();
return result;

Here what I have thus far in the process of transforming it:

Criteria criteria = session.createCriteria(MunicapilityStreet.class);

// No idea what to set here to only get the "municapilityStreet" as result
criteria.setProjection(??);

// I'm not sure if this is correct. With a criteria on a single table it would have been simply "Id".
// Both tables have the column-name Id, and I'm not sure how to differentiate between them.
criteria.add(Restrictions.eq("Street.Id", streetId));

MunicapilityStreet result = (MunicapilityStreet) criteria.uniqueResult();
return result;

Maybe I should create a different question for each, but converting the above HQL query to a Criteria has three points I'm not sure about how to do:

  1. How to do a select with multiple tables (the from MunicapilityStreet munStreet, Street street part)?
  2. How to have a projection to only return a single table of the two (the select municapilityStreet part)?
  3. How to have an equal-Restriction on a column name of one table, even though both tables have the same column-name (the and street.id = :streetId part)?
Nikolai Dmitriev
  • 2,825
  • 1
  • 13
  • 23
Kevin Cruijssen
  • 8,426
  • 8
  • 49
  • 114

1 Answers1

1

I do oppose the rewrite approach, I hope I'm not impolite doing so.

Hibernate allows to control commits (autocommit is by default off), and what you're experiencing are Entitymanager-flushes, they are auto by default and can be disabled too. And, finally, I think, there is no difference if you're running HQL or criteria queries, same machinery underneath.

Nikolai Dmitriev
  • 2,825
  • 1
  • 13
  • 23
  • Is it possible to disable auto-commit for only certain queries, instead of in general? I'm sure things will break if I just disable auto-commit completely. It might solve my current issue, but may cause problems elsewhere where a flush was expected but didn't occur anymore. The problem with this project is that it's active since 2008 with barely any documentation, comments, or git messages (except for the last ~3 years). So rewriting queries is easier to verify I don't break anything else, then disabling auto-commit all-together. If I can disable it per query, that would be great though! – Kevin Cruijssen Oct 04 '19 at 08:40
  • 1
    since entity manager is supposed to be used [single threaded] (https://stackoverflow.com/questions/20997410/entitymanager-in-multithread-app) you should be able to disable it on a per-query-basis (disable, re-enable). I ran into something similar once, and as far as I remember, did it. excluded from warranty ;-) But it is way faster to test than re-writing all queries. – Nikolai Dmitriev Oct 04 '19 at 08:44
  • Hibernate won't auto-flush when using Criterias for select queries, but when using HQL, Hibernate doesn't know whether it is a select/update/delete/etc., so it will always do an auto-flush with the native queries. At least, that's what I understood from my senior colleague and when looking at the Hibernate source code a bit. (PS: Maybe also relevant: we're using Hibernate version 3.5.6-Final - apparently.) – Kevin Cruijssen Oct 04 '19 at 08:56
  • The ones with `session.createQuery("some query")` are HQL though, right (at least, the docs above state _Create a new instance of Query for the given HQL query string._)? So you're saying Hibernate should be able to tell what kind of query it is with `session.createQuery("some query")`, and shouldn't do auto-flushes when it's a `session.createQuery("select ... from ...")` or `session.createQuery("from ...")`? If it is supposed to know based on the String, what could be the causes of the unwanted in between flushes we get now in that case? Where should I search for in the code? – Kevin Cruijssen Oct 04 '19 at 09:08
  • that's right, [says the spec](https://docs.jboss.org/hibernate/core/3.5/reference/en-US/html/querysql.html), but then they're not native ([says the spec](https://docs.jboss.org/hibernate/core/3.5/reference/en-US/html/querysql.html)). If you're sure about your claim, I have nothing at hand now to disprove you. Anyway, autoflush can be disabled explicitly. – Nikolai Dmitriev Oct 04 '19 at 09:17
  • Tbh, I'm not sure about anything with this project, haha. So if you say HQL `createQuery` shouldn't do auto-flush by default (Native `createSQLQuery` is a different story of course), then I believe you. It also wouldn't surprise me if somewhere in this mess a manual flush is done in that case.. This was the first thing I searched for and investigated, but maybe I've accidentally looked past one or skipped it during debugging.. Ah well, I will convert the native HQL queries to Criterias nontheless, but will use your suggestion of disabling/enabling for the complex ones like this. – Kevin Cruijssen Oct 04 '19 at 09:50
  • I've upvoted you, but I'll have to do some implementations and tests before I could accept it. And regardless, I'd still like to see how that query could be done in Criterias, even if it is better to just leave it as is. :) But if your approach works, it's more curiosity than necessarity at that point. – Kevin Cruijssen Oct 04 '19 at 11:54