JPA/Hibernate maximum number of joins? - java

Is there a limit to the number of joins permitted in a JPA/Hibernate query?
Since Hibernate doesn't automatically join, I have to explicitly specify the joins in my JPA/Hibernate query. For example, person has an address, an address has a state. The following query retrieves person(s) with address and state fully loaded:
select p, a, s from person p left join p.address a left join a.state s where ...
As I keep adding joins, I eventually (after 12-13 left joins) reach a limit where Hibernate generates invalid SQL:
Caused by: java.sql.SQLException: Column 'something69_2_' not found.
I do have Hibernate's dialect set to my database implementation, MySQL:
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
Is there an limit to the number joins Hibernate can handle in a single query?
Edit 1: The following is in the log file:
could not read column value from result set: something69_2_; Column 'something69_2_' not found.
However, something69_2_ doesn't appear in the SQL query. It's like Hibernate generated a SQL query and is expecting something69_2_ to be in the results, which is not.
Edit 2: Similar problem documented as an unfixed Hibernate bug HHH-3035
Edit 3: This is a documented Hibernate bug HHH-3636, which has been fixed but is not part of any release yet.
Edit 4: I built hibernate-core 3.3.2-SNAPSHOT which includes bug fix HHH-3636 and it did not address this problem.
Edit 5: The bug behavior seems to be triggered by multiple LEFT JOIN FETCH on ManyToMany or OneToMany relationships. One will work, two or three results in the bug.
Edit 6: Here's the stack trace:
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:629)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:73)
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.doList(Loader.java:2214)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2095)
at org.hibernate.loader.Loader.list(Loader.java:2090)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:388)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:64)
... 69 more
Caused by: java.sql.SQLException: Column 'something69_2_' not found.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1136)
at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2777)
at org.hibernate.type.IntegerType.get(IntegerType.java:28)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:113)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:102)
at org.hibernate.loader.Loader.getKeyFromResultSet(Loader.java:1088)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:553)
at org.hibernate.loader.Loader.doQuery(Loader.java:689)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.doList(Loader.java:2211)
... 77 more
Edit 7: The reason for all these joins is to avoid Hibernate doing n+1 queries, see Hibernate FAQ on How can I avoid n+1 SQL SELECT queries when running a Hibernate query?

The question is why are you trying to make such a complex query in the first place?
Have you considered different approaches? The documentation on improving performance makes some suggestions.

I've once hit the MySQL 5.0 61 table limit with Hibernate:
ERROR 1116 (HY000): Too many tables; MySQL can only use 61 tables in a join

There is nothing within the Hibernate code which limits the number of joins. This could be a bug in the dialect, or a limitation of the database engine. But my money's on a bug unrelated to the number of joins! Have you tried running the SQL directly in an interactive query session?

Have you tried to execute with the actual jdbc driver in use? It might be a issue of the jdbc driver.
Although judging from the name of the column, it is looking for, I'd guess there is some trimming/construction of names going wrong. Definitely looks more like a bug than a intended limit.

Are you aliasing all of your inner joins? And using those aliases? I have seen some really strange behavior with Hibernate when you try and use implicit aliasing in the SELECT clause to do stuff like this (extremely simplified example):
select p.address.state from person p
But if you explicitly declare all your aliases it works just fine. Like this:
select s from person p join p.address a join a.state s
... or even this:
select s from person p join p.address.state s

Related

nativeQuery in JPA

I am new to JPA.
I am trying to create a nativequery with 3 joins on 3 tables.
I have written a nativequery which is something like the below:
Query query=entityManager.createNativeQuery("select p.value,m.value,t.value,t.value from ping as p,ming as m,ting as t where p.id=m.vid and m.id=t.vid");
List<Object[]> list = (List<Object[]>) query.getResultList();
I have 3 tables ping,ming,ting in my database.
I have got syntax error during execution.
check the manual that corresponds to your MySQL server version for the right syntax to use near 'ping as p,ming as m ,ting as t';
Would be helpful if some one can point me the error and What would be the better solution to join different tables over nativequery in JPA.
EDIT:I have successfully run the above query on mysql.
'ping as p,ming as m ,ting as t'
Try to put dot instead coma.
Maybe your syntax is incorrect
Some how alias on the column is causing the problem.
I have tried running the program with out alias on the columns and everything is fine.
Found the similar question here.
hibernate native SQL query error

Select for update not working

My following native query is not working:
Query createNativeQuery = entityManager.createNativeQuery(
"select id from cscache where id=? for update ");
Environment Details:
Mysql 5.6
Jboss 5.1
JPA 1.0
Error:
2014-12-12 10:20:14,581 WARN [org.hibernate.util.JDBCExceptionReporter]
SQL Error: 1064, SQLState: 42000 (http-0.0.0.0-8543-3:)
2014-12-12 10:20:14,581 ERROR [org.hibernate.util.JDBCExceptionReporter]
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'limit 2' at line 1 (http-0.0.0.0-8543-3:)
For Update basically puts a lock on rows, to achieve the same using JPA you need to use Lock Modes. To set the lock, you can use EntityManager or TypeQuery and use LockModeType.PESSIMISTIC_WRITE.
Refer this article
I haven't actually done a for update in hibernate, but I believe you can (and should?) do it on the Session or query object. Why not let hibernate do it instead of executing a native query?
According to the documentation on locking (Chapter 5: Locking, you can set the lock mode on either the session or the query.
Cscache cscache = (Cscache )session.get( Cscache.class, id, LockOptions.UPGRADE );
Specifying the LockOptions should result in a SELECT ... FOR UPDATE being executed.
Not familiar with JPA specifically, but it appears you're not telling it what the value of ? is. Check out setParameter.

update query on 2 tables which are mapped with many-to-many in hibernate?

I tried in Different ways, but could not fixed this Query.
I have 2 tables MerchantOffers & MerchantStore both are mapped with many-to-many. Now i need to update the total count of active offer in every MerchantStore .
some queries i tried
"UPDATE MerchantStore ms
SET ms.offers_count=
(
SELECT count(mo.offer_id)
from MerchantOffers mo
JOIN
mo.stores ms
where mo.offer_status=1
)"
for this i am getting following exception
Caused by: java.sql.SQLException: You can't specify target table 'MerchantStore' for update in FROM clause
When I attempt the following:
"UPDATE MerchantStore ms
JOIN ms.offers mo
SET ms.offers_count=count(*)
where mo.offer_status=1)"
I get the error message:
org.hibernate.hql.ast.QuerySyntaxException: expecting "set", found 'JOIN'
in this way i am failed to write Query.Could any one help.
Thanks in Advance,
raju.

QuerySyntaxException : Hibernate not recognizing the postgres query syntax in java

I am facing problem of executing the following query in java using hibernate for postgres tables.
The query is made up to retrive the data from 3 tables using Inner Joins.
Query :
QryJourney = "SELECT journey.id , journey.operatingday, journey.linename, journey.scheduledeparture, journey.scheduledeparturestopname, journeydetail.stopname , journeydetail.latitude, journeydetail.longitude FROM journey left join journey_journeydetail ON journey.id = journey_journeydetail.journey_id left JOIN journeydetail ON journey_journeydetail.journeydetails_id = journeydetail.id WHERE journey.id = '155815228' ORDER BY journeydetail.schedulearrival";
as soon as it executes, following exception occured.
Exception :
Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ON near line 1, column 268 [SELECT journey.id , journey.operatingday, journey.linename, journey.scheduledeparture, journey.scheduledeparturestopname, journeydetail.stopname , journeydetail.latitude, journeydetail.longitude FROM de.db.journeyTracker.model.journey left join journey_journeydetail ON journey.id = journey_journeydetail.journey_id left JOIN journeydetail ON journey_journeydetail.journeydetails_id = journeydetail.id WHERE journey.id = '155815228' ORDER BY journeydetail.schedulearrival]
Tis query works 100% fine at postgres while executing on its SQL Pane.
Anybody having any idea?
Regards
Usman
Hibernate queries are written in Hibernate Query Language (HQL) not in native SQL. Rephrase your query in HQL or use a native query to use SQL with Hibernate.
Hibernate is an object-relational mapper. It won't just give you a result set. If you want that, use JDBC directly, using PgJDBC.
If you want native domain objects as query results, use Hibernate with HQL or via a native query mapping. Native queries are fiddlier becuse you have to explicitly tell Hibernate how all the result columns map to your result objects.

Hibernate HQL update with a subselect in set clause

I'm trying to do an update in hibernate HQL with a subselect in a set clause like:
update UserObject set code = (select n.code from SomeUserObject n where n.id = 1000)
It isnt working, it is not supported?
Thanks
Udo
I had the same problem, discovered that you need to put bulk updates in side a transaction:
tr = session.getTransaction();
tr.begin();
updateQuery.executeUpdate();
tr.commit;
From the Hibernate documentation:
13.4. DML-style operations
...
The pseudo-syntax for UPDATE and
DELETE statements is: ( UPDATE |
DELETE ) FROM? EntityName (WHERE
where_conditions)?.
Some points to note:
In the from-clause, the FROM keyword is optional
There can only be a single entity named in the from-clause. It can,
however, be aliased. If the entity
name is aliased, then any property
references must be qualified using
that alias. If the entity name is not
aliased, then it is illegal for any
property references to be qualified.
No joins, either implicit or explicit, can be specified in a bulk
HQL query. Sub-queries can be used
in the where-clause, where the
subqueries themselves may contain
joins.
The where-clause is also optional.
While the documentation doesn't explicitly mentions a restriction about the set part, one could interpret that sub-queries are only supported in the where-clause. But...
I found an 4 years old (sigh) issue about bulk update problems (HHH-1658) and according to the reporter, the following works:
UPDATE Cat c SET c.weight = (SELECT SUM(f.amount) FROM Food f WHERE f.owner = c)
I wonder if using an alias in the from-clause would help. Looks like there is some weirdness anyway.

Categories

Resources