Datetime to Date (MySQL) in JPA createQuery error Exception [EclipseLink-8025] - jpa

I'am new in JAVA and JPA.
I use command
select * from asm.attendant where staff_no='0004' and node_code='KT1' and date(attendant_date) = '2013-05-13';
in MySQL it's work
but
when i use in JPA
public List<Attendant> listAttendantByStaffNoAndNodeCodeAndDateWs(String staffNo,String nodeCode,String attendantDateData) throws ParseException {
Date attendantDate = new SimpleDateFormat("yyyy-MM-dd").parse(attendantDateData);
Query result = em.createQuery("SELECT a FROM Attendant a WHERE a.staffNo = :staffNo AND a.nodeCode = :nodeCode AND DATE(a.attendantDate) = :attendantDate", Attendant.class);
result.setParameter("staffNo", staffNo);
result.setParameter("nodeCode", nodeCode);
result.setParameter("attendantDate", attendantDate);
return result.getResultList();
}
it's not work.
error
Caused by: Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [SELECT a FROM Attendant a WHERE a.staffNo = :staffNo AND a.nodeCode = :nodeCode AND DATE(a.attendantDate) = :attendantDate], line 1, column 88: unexpected token [(].
Internal Exception: NoViableAltException(83#[()* loopback of 383:9: (d= DOT right= attribute )*])

DATE() is not valid JPQL. In JPA createQuery() takes JPQL not SQL. If you want SQL use createNativeQuery().
Or, in JPQL just mark the date as a parameter :date any set the parameter to your instance of java.sql.Date.

Related

Exception when using a #ResultSetMapping on a native SQL query with a Spring Data JPA Repository?

I'm currently building a native SQL query with Spring Data JPA that uses a #SqlResultSetMapping. The query looks filters the rows based on certain parameters and then returns all of the columns of an entity table plus additionally it calculates another column on the fly. Something like this:
#Entity
#NamedNativeQuery(
name = "Entity.searchBySearchParams",
resultSetMapping = "SearchResultMapping",
query = "select entity.*, (*calculation*) as anotherField from ..."
)
#SqlResultSetMapping(
name = "SearchResultMapping",
entities = #EntityResult(entityClass = Entity.class),
columns = #ColumnResult(name = "anotherField", type = double.class)
)
public class Entity { ... }
And then I'm trying to call this native, named query from my repository (which extends JpaRepository<T, Long>) like that:
#Query(nativeQuery = true, name = "Entity.searchBySearchParams")
List<Object[]> searchBySearchParams( ... lots of params ... );
Where I'm expecting searchBySearchParams(...)[0] to be of type Entity and searchBySearchParams(...)[1] of type Double.
Unfortunately I'm getting this exception when trying to call the above repository method:
org.springframework.dao.InvalidDataAccessApiUsageException: Cannot create TypedQuery for query with more than one return; nested exception is java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:374)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
....
Which is weird since calling the query and applying my result set mapping directly by invoking the EntityManage#createNamedQuery method worked perfectly fine.
Am I missing something or should I post this to the Spring Data Jira? Neither JPA's nor Spring's documentation provided information for my case ...
More Background Info:
Actually the additional column anotherField is a transitive property on my Entity. I haven't found a way of mapping that column to the transitive property, which is why my repository method currently returns Object[].

Spring JPA repository casting error when using JPQL

I have a PagingAndSorting JPA repository declared. I am using the #Query annotation.
I am getting an exception when I call the get() method on an Optional object from the findById(id) method of the repository.
The weird thing is it only happens when I use JPQL.
The code works if my query is native:
#Override
public BatchDto findById(String id) {
Optional<Batch> findResult = this.batchRepository.findById(id);
if (!findResult.isPresent()) return null;
Batch entity = findResult.get(); **<-------- Cast Exception Here**
BatchDto dto = this.mapper.toDto(entity, BatchDto.class);
List<BatchTransaction> transactions = entity.getTransactions();
dto.setTransactionDtos(mapper.toListDto(transactions, TransactionDto.class));
return dto;
}
Inspecting the findResult object with a breakpoint - I can see:
Optional[net.domain.data.batch#4b8bb6f]
when I have nativeQuery = true in the #Query annotation.
#Query(value = Sql.FindBatchById, nativeQuery = true)
Here is the query being used:
SELECT DISTINCT(B.batchNumber), COUNT(B.batchNumber) as TransactionCount FROM BATCH B WHERE B.batchReferenceNumber = :id GROUP BY B.batchNumber
However if I change it to JPQL and remove the nativeQuery=true attribute - the findResult is
Optional[[Ljava.lang.Object;#76e04327].
and I get a ClassCastException:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to net.domain.data.batch
So bottom line - this works when specify nativeQuery=true and fails when I try to use JPQL.
I would prefer not to specify nativeQuery as we will eventually port this db to Oracle.
First of all the query shown below doesn't return a single Batch instance. Since there are distinct and count aggregate functions, the query will return a List of aggregates.
To be able to read that statistics you can add appropriate method into the batchRepository. Something like this:
#Query("SELECT DISTINCT(B.batchNumber) as dist, COUNT(B.batchNumber) as cnt FROM BATCH B GROUP BY B.batchNumber")
List<Map<Long, Long>> findStatistics();
and then iterate through the list.
UPD
If the id parameter exactly guarantee that will return a single record, you can change a return type to a Map
#Query("SELECT DISTINCT(B.batchNumber) as dist, COUNT(B.batchNumber) as cnt FROM BATCH B WHERE B.batchReferenceNumber = :id GROUP BY B.batchNumber")
Map<Long, Long> findStatisticsById(#Param("id") Long id);

Query Exception: The class of the argument for the object comparison is incorrect

I'm using Spring Data framework!
So I got the following error in eclipse console:
Exception [EclipseLink-6078] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.QueryException
Exception Description: The class of the argument for the object comparison is incorrect.
Expression: [null]
Mapping: [org.eclipse.persistence.mappings.ManyToOneMapping[customerService]]
Argument: [2]
Query: ReadAllQuery(referenceClass=ServiceItem sql="SELECT t1.id_service_item, t1.tenant_id, t1.arrival_date, t1.departure_date, t1.negociation_observations, t1.requested_destination, t1.sale_type, t1.see_in, t1.value_negotiated, t1.fk_customerService, t1.fk_destination FROM service_item t1 LEFT OUTER JOIN customer_service t0 ON (t0.id_customer_service = t1.fk_customerService) WHERE (((t1.sale_type = ?) AND (t1.fk_customerService = ?)) AND (t1.tenant_id = ?))")
org.eclipse.persistence.exceptions.QueryException.incorrectClassForObjectComparison(QueryException.java:601)
But when i run the query in my database client the query works well!
Pass the objects (JPA entities) as parameters, not the object IDs.

JPQL NOT EXISTS in ObjectDB

I am trying to migrate my Spring project from Hibernate to ObjectDB. On ObjectDB page, they say that ObjectDB is 100% compatible with JPA. However, I have problem with this JPQL query:
SELECT e FROM Employee e WHERE e.present = false AND NOT EXISTS
(SELECT c FROM Computer c WHERE c.employeeEntity = e)
ORDER BY e.name
with Hibernate, there was no problem with this query, but ObjectDB throws exception:
com.objectdb.o.UserException: Unexpected query token 'EXISTS'
Second problem is with Criteria Language. This code:
In<Employee> inExpression = cb.in(root.get(Computer_.employeeEntity));
for (Long id : emplIds) {
Employee e = new Employee(id);
inExpression = inExpression.value(e);
}
list.add(inExpression);
was working with Hibernate, with ObjectDB it is throwing:
com.objectdb.o.UserException: Unexpected query token ':l2'
at com.objectdb.o.MSG.d(MSG.java:61)
at com.objectdb.o.TKN.J(TKN.java:765)
at com.objectdb.o.QNF.B(QNF.java:894)
at com.objectdb.o.QNF.I(QNF.java:1294)
at com.objectdb.o.QNF.k(QNF.java:315)
at com.objectdb.o.QNF.H(QNF.java:1270)
at com.objectdb.o.QNF.k(QNF.java:210)
at com.objectdb.o.QNF.t(QNF.java:611)
at com.objectdb.o.QNF.t(QNF.java:605)
at com.objectdb.o.QNF.k(QNF.java:218)
at com.objectdb.o.QNF.j(QNF.java:135)
at com.objectdb.o.QRC.z(QRC.java:321)
at com.objectdb.o.QRC.v(QRC.java:212)
at com.objectdb.o.QRC.u(QRC.java:166)
at com.objectdb.o.QRM.U6(QRM.java:250)
at com.objectdb.o.MST.U6(MST.java:933)
at com.objectdb.o.WRA.U6(WRA.java:291)
at com.objectdb.o.WSM.U6(WSM.java:113)
at com.objectdb.o.STC.r(STC.java:449)
at com.objectdb.o.SHN.aj(SHN.java:489)
at com.objectdb.o.SHN.K(SHN.java:156)
at com.objectdb.o.HND.run(HND.java:132)
at java.lang.Thread.run(Unknown Source)
Does anybody have any idea how to solve these problems?
Milan
com.objectdb.o.UserException: Unexpected query token 'EXISTS'
ObjectDB doesn't know EXISTS. See http://www.objectdb.com/java/jpa/query/jpql/comparison.
Instead you can use IS NOT NULL to validate the existence. Be aware that SELECT c FROM Computer c WHERE c.employeeEntity = e must return a single instance and not a multi row resultset.
This is not an ObjectDB issue, cause it is rooted in SQL / sql dialect.
See https://stackoverflow.com/a/6808503/1549387
com.objectdb.o.UserException: Unexpected query token ':l2'
Can you print the stack trace of this? It looks like a unknown named parameter. Could you send the logging level to FINE or FINEST to view the generated SQL?

JPA createNativeQuery call procedure with non standart name

I'm trying to call an Oracle procedure using Persistence API:
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void removeProcess(User user, BigDecimal processId) {
EntityManager em = emb.createEntityManager(user);
em.createNativeQuery("{ call DOF.DF#DEL_PROCESS(?) }")
.setParameter(1, processId)
.executeUpdate();
em.close();
}
And I got the following exception:
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Invalid column index
Error Code: 17003
Call: { call DOF."DF?)" }
bind => [1 parameter bound]
If i copy DF#DEL_PROCESS to DF_DEL_PROCESS all works fine. How can I escape # in the procedure name??
'#' is the default parameter marker used internal in EclipseLink.
You can change this using the query hint, "eclipselink.jdbc.parameter-delimiter"
Also, if you inline the parameter instead of using setParameter() it should also work.