Spring hibernate : Could not extract result set metadata - java

I try to use a native query in my Dao (extended from JpaRepository), but i get this exception :
org.springframework.orm.jpa.JpaSystemException: Could not extract result set metadata; nested exception is org.hibernate.HibernateException: Could not extract result set metadata
Here is my native query:
#Repository
public interface BenchDao extends JpaRepository<Bench, Long> {
#Query(nativeQuery=true,value="UPDATE TF_BENCH SET ISDELETED = 1, SEQ = (select CASE WHEN (min(BENCH.SEQ) < 1) THEN (min(BENCH.SEQ)-1) ELSE -1 END from TF_BENCH BENCH WHERE BENCH.STAGE = (select BENCH.STAGE from TF_BENCH BENCH WHERE id =29302)) WHERE id =29302")
void deleteBench();
When i try this request on Oracle SQL developper it works, but through spring and hibernate it doesn't.
In the stack trace exeception I have also this message :
Caused by: java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
I've tried to google exception messages, but I found nothing...

I think that a better solution was to add the #Modifying annotation to your method.
See more on the following Answer : Spring Data JPA delete native query throwing exception

I've found a solution : if someone need :
#Repository
public class BenchDaoCustomImpl implements BenchDaoCustom {
#PersistenceContext
private EntityManager em;
public void deleteBench(Long benchId) {
this.em.createNativeQuery("UPDATE TF_BENCH SET ISDELETED = 1, SEQ = (select CASE WHEN (min(BENCH.SEQ) < 1) THEN (min(BENCH.SEQ)-1) ELSE -1 END from TF_BENCH BENCH WHERE BENCH.STAGE = (select BENCH.STAGE from TF_BENCH BENCH WHERE id =?0)) WHERE id =?0")
.setParameter(0, benchId)
.executeUpdate();
}
}

Related

Could not extract ResultSet When i using Native Query in Spring Jpa

I am trying to get true or false, with some compare condition using Spring JPA native query. But I got following Exception,
could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
The query I am trying is:
SELECT case when ABS(am_savedagent.AGENT_VERSION)< 1.8 then 'true' else 'false' end as bool
FROM am_savedagent where am_savedagent.BOX_ID="ots-JIO6Yn0jZbxs";
My Repository
public interface SavedAgentRepository extends JpaRepository<SavedAgentDetails, String>, JpaSpecificationExecutor<SavedAgentDetails> {
#Query(value = "SELECT case when ABS(SavedAgentDetails.agentVersion)< ?1 then 'true' else 'false' end as bool FROM SavedAgentDetails where SavedAgentDetails.boxId=?2", nativeQuery = true)
public Optional<List<Object>> findByAgentVersionAndBoxId(String currentVersion, String boxid);
}
I can't find y the Errors Comming. please help me, someone.
Since you are using native query =true,
that's why you need to use the table name and not the entity name inside your query.
Try this -->
public interface RegisterAgentRepository extends JpaRepository<RegisterAgentDetails, String>, JpaSpecificationExecutor<RegisterAgentDetails> {
#Query(value = "SELECT case when ABS(am_registeragent.AGENT_VERSION)< ?1 then 'true' else 'false' end as bool FROM am_registeragent where am_registeragent.SAASBOX_ID=?2", nativeQuery = true)
public Optional<List<Object>> findByAgentVersionAndSaasboxId(String currentVersion, String saasboxid);
}

Creating query exception in JPA while creting custom query method

JPA repository throwing Error for custom query method:
org.h2.jdbc.JdbcSQLException: Table "NBMRBANKDTLSENTITY" not found; SQL statement:
select NBMRBankDtlsEntity from NBMRBankDtlsEntity where NBMRBankDtlsEntity.ipphId = ? [42102-191]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
Class :
#Repository
public interface NBMRBankDtlsRepository extends JpaRepository<NBMRBankDtlsEntity, Long> {
#Query(value ="select n from NBMRBankDtlsEntity n where n.ipphId = :ipphId",nativeQuery = true)
Optional<NBMRBankDtlsEntity> findByIPPHId(#Param("ipphId") Long ipphId);
}
The error message tells you: Table "NBMRBANKDTLSENTITY" not found. Therefore it probably doesn't exist. To fix this you'll have to create the table, manually through a script or through hibernates schema creation feature.
I am already creating a table also inserting the record, After that only i am calling this custom query method.
I have found the issue as i am using nativeQuery = true so it is expecting normal sql query to query DB directly not the java query which is creating issue. Now after changing below it works fine ,
#Query(value = "SELECT * from NB_MR_BANK_DTLS WHERE IPPH_ID = :ipphId",nativeQuery = true)
For java query we can use directly as it internally converts to SQL while querying the DB,
#Query(value = "select p from NBMRBankDtlsEntity p WHERE p.ipphId = :ipphId")

Hibernate custom delete query multiple rows

Still new to hibernate custom queries.
My table is
ID TID R1 Position
1 1 1 2
2 1 1 3
I want a custom query to delete rows with TID 1 and R1 1
My current sql looks like
#Query(value = "delete from Table t where t.TID= :tid and t.R1 = :r1", nativeQuery = true)
void deleteByTIDAndR1(#Param("tid") Integer TID, #Param("r1") Integer r1);
It gives me the following error:
.springframework.orm.jpa.JpaSystemException: could not extract ResultSet; nested exception is org.hibernate.exception.GenericJDBCException: could not extract ResultSet] with root cause
My controller retrieves the right tid and r1 ID's.
Is it even possible to delete multiple rows at once? And where could my error be?
Edit
After I add #Modyfying to the query i get the error
TransactionRequiredException: Executing an update/delete query
And after i add #Transactional in combination with #Modifying i get
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 't where t.tid= 1 and t.R1 = 99' at line 1
I think you lack the #Modifying annotation, indicating a query that modify the database:
#Modifying
#Query(value = "delete from Table where TID= :tid and R1 = :r1", nativeQuery = true)
void deleteByTIDAndR1(#Param("tid") Integer TID, #Param("r1") Integer r1);
And yes this method can delete zero, one or more rows.

Query needed to check if an email already exist in a DB(Java Persistence API)

I try to figure out what is the problem with this method that uses JPQL to validate if an email already exist in the DB, for some reason it does not work. Someone can have a look? Or give another alternative query more simple?
#Override
public boolean emailAlreadyExists(String value) {
Query checkEmailExists = em.createQuery("SELECT COUNT(b.email) FROM "
+ Buyer.class.getName() + " b WHERE email = :emailparam");
checkEmailExists.setParameter("emailparam", value);
long matchCounter = 0;
matchCounter = (Long) checkEmailExists.getSingleResult();
if (matchCounter > 0) {
return true;
}
return false;
}
This is part of the console output:
Caused by: Exception [EclipseLink-8024] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [SELECT COUNT(b.email) FROM entities.Buyer b WHERE b.email = :emailparam], line 1, column 35: syntax error at [.].
Internal Exception: MismatchedTokenException(83!=78)
Im sure it has to do something with the syntax. But where i am making the mistake?
Typically JPA uses short class names (without package name). And I personally have never used aliases in JPA queries, so I am not sure they are supported there. And you do not need them in your query. And I am not sure the space between = and : is permitted.
So, try this: SELECT COUNT(email) FROM Buyer WHERE email=:emailparam
I hope this will work. In this case try to play with the query and see which one of the changes really does the work.

Why EclipseLink Query cache only works when I use query.getSingleResult()?

My entity has a named query which looks like this:
#NamedQuery(name = "Person.find", query = "select p from Organization p where p.name=:NAME")
In my code I want to set the query cache hint:
query.setHint("eclipselink.cache-usage", "CheckCacheThenDatabase");
If I try to get whole result list:
List<Person> result = query.getResultList();
EclipseLink throws an exception:
Exception [EclipseLink-6124] (Eclipse Persistence Services - 1.0.1 (Build 20080905)): org.eclipse.persistence.exceptions.QueryException
Exception Description: Required query of class org.eclipse.persistence.queries.ReadAllQuery, found class org.eclipse.persistence.queries.ReadObjectQuery
If I try to get only a single result, it works:
Person person = query.getSingleResult();
If I remove the query hint, then getResultList() works also.
I don't understand the exception - isn't it saying that it is specifically expecting getResultList()?? What am I doing wrong?
EclipseLink documentation says:
"EclipseLink does not support the cache usage for native queries or queries that have complex result sets such as returning data or multiple objects."
Also the documentation says:
"CheckCacheThenDatabase – You can configure any read-object query to check the cache completely before you resort to accessing the database."
So the behaviour seems to be ok, I just found the exception misleading.
EDIT: Try something like this in the entity definition, that should be enough: (Coded on the web page so there can be errors)
Entity
#Cache(expiry = 3600000, // 1 hour size = 10000)
#NamedQueries({
#NamedQuery(name = "Person.findByPK", query = "select p from Person p " +
"where p.name=:NAME",
hints = {
#QueryHint(name = QueryHints.CACHE_USAGE,
value = CacheUsage.CheckCacheThenDatabase),
#QueryHint(name = QueryHints.QUERY_TYPE, value = QueryType.ReadObject)
}
})

Categories