How to use Oracle query hint in Hibernate - oracle

I am trying to use Oracle hint in Hibernate to call force index, but didn't find any proper API in Hibernate 3.6.10.Final.
I somehow tried with projections in Hibernate criteria:
proList.add(Projections.sqlProjection("/*+ INDEX_DESC(CONTACT_USER_FK_I) */", new String[]{}, new Type[]{}));
proList.add(Projections.property("objectId"));
criteria.setProjection(proList);
return criteria.list();
But I am getting the exception below:
EXCEPTION
Caused by: 8 SQL Error (could not execute query; SQL [select /*+ INDEX_DESC(CONTACT_USER_FK_I) */, this_.CONTACT_ID as y0_ from R4GDEV01_MBW.CONTACT this_ w
here this_.USER_ID=? and this_.ADDRESS_BOOK_ID in (?) and this_.DELETION_DATE is null order by lower(this_.FIRSTNAME) asc]; nested exception is org.hibernate
.exception.SQLGrammarException: could not execute query)
at com.fusionone.pml.dao.hibernate.AbstractDao.executeCallback(AbstractDao.java:391)
at com.fusionone.pml.dao.hibernate.AbstractContactDao.searchContacts(AbstractContactDao.java:1019)
at com.fusionone.nab.core.service.impl.MergeServiceImpl.getFilteredContactIds(MergeServiceImpl.java:154)
... 91 more
I found out that the projection is appending a , after query hint.
Is there any other way to use Oracle query hint in Hibernate 3.6.10 criteria or in HQL?
Thanks

You should try to search first. Here is a simple trick to solve this, just transform the hint into a column:
"/*+ INDEX_DESC(CONTACT_USER_FK_I) */ 1 as MYHINT"

Your problem is that there is nothing previous to ,. Due to you want to add a projection on objectIdattribute, you could transform your criteria to somenthing like this:
Projections.sqlProjection("/*+ INDEX_DESC(CONTACT_USER_FK_I) */ objectId", new String[]{}, new Type[]{}))

Related

I am getting ORA-01008: not all variables bound : Error when I am trying to read a oracle DB via SQLPagingQueryProviderFactoryBean

Below is the snippet of the code of Spring boot JDBC item reader which call paging Query query provider.
final SqlPagingQueryProviderFactoryBean testVar = new SqlPagingQueryProviderFactoryBean(); SqlPagingQueryProviderFactoryBean.setDataSource(dataSource); SqlPagingQueryProviderFactoryBean.setSelectClause("select *"); SqlPagingQueryProviderFactoryBean.setFromClause("from "+ tableName); SqlPagingQueryProviderFactoryBean.setWhereClause("where processtime is NULL AND RECORN_NUM BETWEEN :startPos AND :endPos) return ..
Error : Org.springframework.jdbc.uncategorizedSQLException : StatementCallBack; uncategorized SQLException for SQL [ SELECT * From ( SELECT * FROM table_name WHERE processtime is NULL AND RECORN_NUM BETWEEN :startPos AND :endPos order by RECORD_NUM <=100]; SQL state [72000]; error code[10008]: ORA-10008: not all variables bound; nested Exception
I am trying to read the data from the oracle table via spring boot batch job using a JDBC item reader.
First, SQL keywords like select, from, etc can be omitted.
The problem is that you are not providing sorting keys. You need to provide a sort key, as mentioned in the Javadoc of AbstractSqlPagingQueryProvider. This impacts the way SQL queries are generated.
If you declare the SqlPagingQueryProviderFactoryBean as a bean, the validation of sort keys should be triggered and you would have an exception earlier at configuration time.

spring data jpa specification join fetch is not working

I am trying to use Spring Data JPA Specificaiton to query data, but I got some problem here.
The Java code is as below:
List<NoticeEntity> studentNoticeEntityList = noticeRepository
.findAll((root, criteriaQuery, criteriaBuilder) -> {
criteriaQuery.distinct(true);
root.fetch(NoticeEntity_.contentEntitySet, JoinType.LEFT);
Predicate restrictions = criteriaBuilder.conjunction();
SetJoin<NoticeEntity, UserNoticeEntity> recipientNoticeJoin = root
.join(NoticeEntity_.recipientNoticeEntitySet, JoinType.INNER);
recipientNoticeJoin.on(criteriaBuilder.equal(
recipientNoticeJoin.get(UserNoticeEntity_.recipientStatus), NoticeRecipientStatus.Unread));
Join<UserNoticeEntity, WeChatUserEntity> recipientUserJoin = recipientNoticeJoin
.join(UserNoticeEntity_.user);
restrictions = criteriaBuilder.and(restrictions,
criteriaBuilder.equal(recipientUserJoin.get(WeChatUserEntity_.id), id));
// recipientNoticeJoin.fetch(UserNoticeEntity_.user, JoinType.INNER);
return restrictions;
});
When I comment the code "recipientNoticeJoin.fetch(UserNoticeEntity_.user, JoinType.INNER);", it is working fine, but when I un-comment this, I will get error:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
So, I am wondering if join fetch is supported by using Specification way, or there is something wrong with my code.
I know there is another way by using #Query("some hql"), but somehow I just prefer to use the Specification way.
Thanks a lot.
The error specifies that you're missing an entity from your select list. Try this:
criteriaQuery.multiselect(root, root.get(NoticeEntity_.recipientNoticeEntitySet);
Also, hibernate may run a count query first to determine the number of results, and this can cause the above error. You can avoid this breaking by checking the return type of the query before adding the fetch.
Eager fetching in a Spring Specification

SimpleJdbcCall : No function exist error

I am getting Exception while executing store procedure. Exception is as below
org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback;badSQLgrammar [{call find_spot()}]; nestedexception is org.postgresql.util.PSQLException: ERROR: functionfind_spot()
does not exist Hint: No function matches the given name and argument types. You might need to add explicit type casts.Position:15
Its saying function find_spot() does not exist but I checked in database this procedure is there. I am using Postgresql [DBeaver]
Can anyone help me to solve this?
You should cast a json to make search or use the json access query, see the examples:
select * from table where cast(field_json as varchar(500)) !~ 'reg_ex' and id = 11
or
select field_json->>'key' from table where field_json->>'key' ilike 'value'

How to set limit for a hibernate query

How can I set a limit to this hql query? When I add the limit keyword in the query, an error is thrown.
#Query("from voucher v where v.voucherType.typeDescription = :typeDescription and v.denomination = :denomination")
public List<Voucher> findByVoucherTypeAndDenomination(#Param("typeDescription") String typeDescription,#Param("denomination") BigDecimal denomination);
When you call your query add the following:
.setFirstResult(firstResult).setMaxResults(limit);
setFirstResult is the (optional) offset, setMaxResults is the limit.
UPDATE
Docs:
http://docs.jboss.org/hibernate/orm/3.6/javadocs/org/hibernate/Query.html#setMaxResults(int)
If you use entityManager, it can be like:
entityManager.createQuery("yourQuery").setFirstResult(0).setMaxResults(5);
You can use two method of Query object.
setFirstResult() // offset
setMaxResults() // limit
but you can not use it in HQL because limit is database vendor dependent so hibernate doesn't allow it through hql query
Limit was never a supported clause in HQL. You are meant to use setMaxResults().

Oracle XMLDB's XMLCAST and XMLQUERY incompatible with iBatis?

I've been trying to select a list of values from XMLs stored in an
XMLType column but I keep getting the errors which are listed at the
tail end of this post.
The select id is
getXMLFragment
, and the relevant subset of the
sqlmap.xml is as follows:
<select id="getXMLFragment" resultClass="list">
SELECT
XMLCAST(XMLQUERY('$CUSTOMER/CUSTOMER/DETAILS/
CUST_NAME/text()' PASSING CUSTOMER AS
"CUSTOMER" RETURNING CONTENT) AS VARCHAR2(20))
AS customers FROM SHOP.CLIENT_INFO
</select>
(CUSTOMER is an XMLType column in CLIENT_INFO)
and I call the statement using
List<String> custNames= (List<String>)
sqlMap.queryForList("getXMLFragment");
I am using ibatis-2.3.4.726.jar.
Is it because iBatis does not recognise XMLDB queries and hence,
tokenizes the string wrongly? On a sidenote, I have implemented
XMLTypeCallback.java to handle XMLType insertions successfully, and I
think it will work should I wish to retrieve the entire XML. However,
in this case, I need to extract only individual values due to
requirements. A workaround would be greatly appreciated.
Thanks in advance.
The exceptions generated are listed below:
--- The error occurred in sqlMap.xml.
--- The error occurred while preparing the mapped statement for
execution.
--- Check the getXMLFragment.
--- Check the SQL statement.
--- Cause: java.util.NoSuchElementException
at
com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:
204)
at
com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryForList(MappedStatement.java:
139)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:
567)
at
com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExecutorDelegate.java:
541)
at
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:
118)
at
com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionImpl.java:
122)
at
com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForList(SqlMapClientImpl.java:
98)
at Main.main(Main.java:60)
Caused by: java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:332)
at
com.ibatis.sqlmap.engine.mapping.sql.simple.SimpleDynamicSql.processDynamicElements(SimpleDynamicSql.java:
90)
at
com.ibatis.sqlmap.engine.mapping.sql.simple.SimpleDynamicSql.getSql(SimpleDynamicSql.java:
45)
at
com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:
184)
... 7 more
Update: We just need to repeat '$' once such that the sql is "....XMLQUERY('$$CUSTOMER....." The tokenization works fine after that and the query executes successfully.

Resources