Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[eclipselink-users] Converter not getting called when operator or function is used in JPQL

Problem Statement: 
------------------ 
1. Converter is not getting called, when OPERATOR is used in JPQL query.
2. In example depicted below, entity 'Domain' has creationDate with type
java.lang.String.
3. Database column data type is DATE.
4. Hence converter 'MyDateConverter' is used for java.lang.String to DATE
convertion and vice-versa.
5. Following JPQL Query without OPERATOR call works properly when dateParam
is set as java.lang.String value:
   select a from learning.entity.Domain a where a.creationDate = :dateParam
6. But following JPQL Query with OPERATOR call fails when dateParam is set
as java.lang.String value:
   select a from learning.entity.Domain a where a.creationDate =
OPERATOR('Nvl', :dateParam, a.creationDate)

If we set dateParam as java.sql.Date value, then query mentioned in point 6
above works properly.
But this is inconsistent behaviour, Eclipselink should internaly make call
to converter to convert java.lang.String to java.sql.Date, as it does for
query mentioned in point 5 above.
Can anyone suggest me a way to get this working.

Example explaining the above scenario: 
-------------------------------------- 

Entities: 
--------- 

package learning.entity;

public class Domain {

	private DomainKey domainKey;
	private String name;
	private String description;
	private String creationDate;

	public DomainKey getDomainKey() {

		return domainKey;
	}

	public void setDomainKey(DomainKey domainKey) {

		this.domainKey = domainKey;
	}

	public String getName() {

		return name;
	}

	public void setName(String name) {

		this.name = name;
	}

	public String getDescription() {

		return description;
	}

	public void setDescription(String description) {

		this.description = description;
	}

	public String getCreationDate() {

		return creationDate;
	}

	public void setCreationDate(String creationDate) {

		this.creationDate = creationDate;
	}
}


package learning.entity;

public class DomainKey {

	private String domainId;
	private int domainVersion;

	public String getDomainId() {

		return domainId;
	}

	public void setDomainId(String domainId) {

		this.domainId = domainId;
	}

	public int getDomainVersion() {

		return domainVersion;
	}

	public void setDomainVersion(int domainVersion) {

		this.domainVersion = domainVersion;
	}
}

Converter: 
---------

package learning.converters;

import java.sql.Date;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;

public class MyDateConverter implements Converter {

	private static final long serialVersionUID = 1115687221435944421L;

	@Override
	public Object convertObjectValueToDataValue(Object objectValue, Session
session) {

		Object convertedValue = null;
		DateFormat lFormatter = new SimpleDateFormat("dd-MM-yyyy");
		try {
			convertedValue = objectValue == null ? null : new
Date((lFormatter.parse((String) objectValue)).getTime());
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
		return convertedValue;
	}

	@Override
	public Object convertDataValueToObjectValue(Object dataValue, Session
session) {

		Object convertedValue;
		DateFormat lFormatter = new SimpleDateFormat("dd-MM-yyyy");
		if (dataValue instanceof java.sql.Timestamp) {
			convertedValue = dataValue == null ? null :
lFormatter.format((java.sql.Timestamp) dataValue);
		} else {
			convertedValue = dataValue == null ? null :
lFormatter.format(((java.sql.Date) dataValue).getTime());
		}
		return convertedValue;
	}

	@Override
	public boolean isMutable() {

		return false;
	}

	@Override
	public void initialize(DatabaseMapping mapping, Session session) {

	}
}

Tables: 
------- 
create table TST_DOMAINS_B
(
  DOMAIN_CODE    VARCHAR2(100),
  DOMAIN_NAME    VARCHAR2(100),
  DOMAIN_DESC    VARCHAR2(100),
  DOMAIN_VERSION NUMBER,
  CREATION_DATE  DATE
)

Mappings: 
--------- 
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings version="2.4"
	xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm";
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
	xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/orm
http://www.eclipse.org/eclipselink/xsds/eclipselink_orm_2_4.xsd";>

	<converter name="Date" class="learning.converters.MyDateConverter" />

	<entity class="learning.entity.Domain">
		

		

		<attributes>
			<embedded-id attribute-type="learning.entity.DomainKey"
				name="domainKey">
				<attribute-override name="domainId">
					<column name="DOMAIN_CODE" />
				</attribute-override>
				<attribute-override name="domainVersion">
					<column name="DOMAIN_VERSION" />
				</attribute-override>
			</embedded-id>
			<basic name="name">
				<column name="DOMAIN_NAME" />
			</basic>
			<basic name="description">
				<column name="DOMAIN_DESC" />
			</basic>

			<basic attribute-type="java.lang.String" name="creationDate">
				<column name="creation_date" />
				<convert>Date</convert>
			</basic>

		</attributes>
	</entity>

	<embeddable class="learning.entity.DomainKey">
		<attributes>
			<basic attribute-type="java.lang.String" name="domainId" />
			<basic attribute-type="int" name="domainVersion" />
		</attributes>
	</embeddable>
</entity-mappings>

Test Case: 
----------

package learning.service;

import java.text.ParseException;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class EclipseLinkJPATest {

	public static void main(String[] args) throws ParseException {

		EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("MyEclipseLinkJPALearning");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		//Query without OPERATOR call works properly when dateParam is set as
java.lang.String value
		try {
			Query q = entityManager.createQuery("select a from learning.entity.Domain
a where a.creationDate = :dateParam");
			q.setParameter("dateParam", "26-05-2014");
			List data = q.getResultList();
			System.out.println("query result: " + data);
		} catch (Exception e) {
			e.printStackTrace();
		}
		//Query with OPERATOR call fails when dateParam is set as java.lang.String
value
		try {
			Query q1 = entityManager.createQuery("select a from
learning.entity.Domain a where a.creationDate = OPERATOR('Nvl', :dateParam,
a.creationDate)");
			q1.setParameter("dateParam", "26-05-2014");
			List data1 = q1.getResultList();
			System.out.println("query result: " + data1);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Exception Log: 
-------------- 

javax.persistence.PersistenceException: Exception [EclipseLink-4002]
(Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5):
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLDataException: ORA-01843: not a valid month

Error Code: 1843
Call: SELECT creation_date, DOMAIN_DESC, DOMAIN_NAME, DOMAIN_CODE,
DOMAIN_VERSION FROM TST_DOMAINS_B WHERE (creation_date = NVL(?,
creation_date))
	bind => [26-05-2014]
Query: ReportQuery(referenceClass=Domain sql="SELECT creation_date,
DOMAIN_DESC, DOMAIN_NAME, DOMAIN_CODE, DOMAIN_VERSION FROM TST_DOMAINS_B
WHERE (creation_date = NVL(?, creation_date))")
	at
org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:378)
	at
org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
	at
org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:469)
	at learning.service.EclipseLinkJPATest.main(EclipseLinkJPATest.java:31)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services -
2.5.1.v20130918-f2b9fc5):
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLDataException: ORA-01843: not a valid month

Error Code: 1843
Call: SELECT creation_date, DOMAIN_DESC, DOMAIN_NAME, DOMAIN_CODE,
DOMAIN_VERSION FROM TST_DOMAINS_B WHERE (creation_date = NVL(?,
creation_date))
	bind => [26-05-2014]
Query: ReportQuery(referenceClass=Domain sql="SELECT creation_date,
DOMAIN_DESC, DOMAIN_NAME, DOMAIN_CODE, DOMAIN_VERSION FROM TST_DOMAINS_B
WHERE (creation_date = NVL(?, creation_date))")
	at
org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
	at
org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:682)
	at
org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
	at
org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
	at
org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570)
	at
org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
	at
org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
	at
org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299)
	at
org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:694)
	at
org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2738)
	at
org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllReportQueryRows(ExpressionQueryMechanism.java:2675)
	at
org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:848)
	at
org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
	at
org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127)
	at
org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:403)
	at
org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215)
	at
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
	at
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
	at
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
	at
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1740)
	at
org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258)
	... 2 more
Caused by: java.sql.SQLDataException: ORA-01843: not a valid month

	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
	at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
	at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
	at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
	at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
	at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
	at
oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)
	at
oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:886)
	at
oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1175)
	at
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1296)
	at
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613)
	at
oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3657)
	at
oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1495)
	at
org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007)
	at
org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642)
	... 21 more



--
View this message in context: http://eclipse.1072660.n5.nabble.com/Converter-not-getting-called-when-operator-or-function-is-used-in-JPQL-tp167580.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.


Back to the top