Select for update not working - java

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.

Related

I need to lock row from reading by other transaction

I have requirement where I need to lock rows of table for reading by other Transaction.
Means,
If Transaction 1 reads few records for table 1. These rows should not be read by Transaction2
I am having following environment
1. MySQL
2. Jboss 5.1
3. JPA 1.0
Please let me know your suggestions
I am using native query select for update
Query createNativeQuery = entityManager.createNativeQuery("select id from cscache where id = ? for update ");
But it is giving following error
2014-12-12 09:35:42,326 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-5:)
You can use like that.
LOCK TABLES tbl_name READ;
For more details . please click here
SELECT FOR UPDATE should do the trick.
YourClass c = em.find(YourClass.class, yourId,
LockModeType.PESSIMISTIC_WRITE);
or
TypedQuery<Table> q = em.createQuery("select t from Table t where ...", Table.class);
q.setLockMode(LockModeType.PESSIMISTIC_WRITE);

OpenJPA check column length when query

Entity Class
#Id
#Column(length=3)
private String BankID;
DAO Class
String sSQL = "SELECT x FROM Bank x WHERE x.BankID =?1 ";
Query aQuery = m_aEntityManager.createQuery(sSQL);
aQuery.setParameter(1, sBankID);
If I pass '001' to sBankID, everything is OK.
But if I pass '0001' to sBankID, OpenJPA just throw PersistenceException: DB2 SQL error: SQLCODE: -302, SQLSTATE: 22001, SQLERRMC: null
Is there anyway just to set OpenJPA turn off column lenth validation?(if I don't want modify any eneity and dao source codes)
DB2 9, OpenJPA 1.2
Thanks a lot!
Is there anyway just to set OpenJPA turn off column lenth
validation?(if I don't want modify any eneity and dao source codes)...
DB2 SQL error: SQLCODE: -302, SQLSTATE: 22001, SQLERRMC: null
This exception is coming from DB2 and OpenJPA is merely exposing the problem as a PersistenceException. You will need to pass in proper length data to get the exception to go away... or modify your table definition.

JPA2 CreateQuery SQL Server Dialect

The function CreateQuery(string) in java.persistence.Query is returning a different query from what I requested.
My input string to the function is:
from Underlying where (SUBSTRING(ticker, (charindex('.', ticker) +
1), (len(ticker) - charindex('.', ticker))) in (:exchanges) order by
ticker
When I call getResultList() on the Query, I see the following sql in my log:
Hibernate: select underlying0_.id as id63_, underlying0_.updated_date
as updated2_63_, underlying0_.updated_user as updated3_63_,
underlying0_.version as version63_, underlying0_.adr as adr63_,
underlying0_.desk as desk63_, underlying0_.enabled as enabled63_,
underlying0_.forward_start_enabled as forward8_63_,
underlying0_.ticker as ticker63_, underlying0_.vol_shift_type as
vol10_63_ from underlyings underlying0_ where
(substring(underlying0_.ticker, charindex('.', underlying0_.ticker)+1)
in (?)) order by underlying0_.ticker
This is query is not a valid SQL Server 2008 query and as expected, I received an error:
SQL Error: 174, SQLState: S0001
The substring function requires 3 argument(s).
Any one know what is going on here?
FYI, I have tried the following two dialects 1) org.hibernate.dialect.SQLServer2008Dialect, and 2) org.hibernate.dialect.SQLServer2008Dialect
Issue is with function charindex. It is not available in the dialect, therefore causes incorrect mapping. Changing this to the HQL function "locate" (keeping args constant) fixed the issue. My query now works in SQL Server 2008:
...where (substring(underlying0_.ticker, charindex('.',
underlying0_.ticker)+1, len(underlying0_.ticker)-charindex('.',
underlying0_.ticker)) in (?))...
Error clearly mention that SUBSTRING() function require 3 Arguments you are passing 2. thus error is in your query.
read about SUBSTRING() Function

Alter PostgreSQL sequence using Hibernate native sql query

My problem seems to be very simple but I have hard time resolving it.
I want to alter an PostgreSQL sequence using Hibernate via native sql query (other solutions are also welcomed) using next code:
Query query = getSession()
.createSQLQuery("ALTER SEQUENCE users_id_seq RESTART WITH ?")
.setInteger(0, 1);
query.executeUpdate();
But I am getting this error:
Hibernate:
ALTER SEQUENCE users_id_seq RESTART WITH ?
hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42601
hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: syntax error at or near "$1"
Best I'm aware, you cannot prepare that statement.
If hibernate allows it, emulate the prepared statement, instead of sending it to the server. If not, sanitize the variable and issue the final statement directly.
Alternatively, wrap it in a function with dynamic SQL:
http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

JPA/Hibernate maximum number of joins?

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

Categories

Resources