Home » Eclipse Projects » EclipseLink » TYPE() fails in projection query result: EclipseLink ConversionException
TYPE() fails in projection query result: EclipseLink ConversionException [message #712438] |
Sun, 07 August 2011 04:45  |
Eclipse User |
|
|
|
EclipseLink2.2
GlassFish3.1
Oracle 10gR2 for Mac OS X.
Netbeans 7
JPA2
JavaEE6
I am exploring using projection queries to expose lightweight slices of otherwise very heavy entities to a JSF user interface.
For want of a better expression I am calling the constructed objects to hold the projection query results "View DTOs", although they are not "across the wire" Data Transfer Objects. Each View DTO contains sufficient information to construct a JSF link with title and an outcome and id as query parameter, but no expensive relationships.
I need, absolutely imperatively, to be able to also access the class of the entity "matching" each View DTO object, and I store this with the View DTO on construction. I am attempting to access this using TYPE() in the query result.
So for example, I have a TagSet entity with a List<Tag> tags. A query for all TagSetView instances matching
every TagSet within a given Project is:
public List<TagSetView> jqpl_tagSetViews(Project project) {
//cf. Special Result Types, Pro JPA2 p.193
return em.createQuery(
"SELECT NEW com.greensoft.entity.dto.tag.TagSetView(TYPE(t),t.id,t.name) "+
"FROM TagSet t "+
"WHERE t.project = :project "+
"ORDER BY t.name",
TagSetView.class)
.setParameter("project",project)
.getResultList();
}
With the View DTO constructor:
public TagSetView(Class entityClass, Long id, String name) {
super(entityClass,id,name);
}
This fails with:
Exception [EclipseLink-3007] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [TagSet], of class [class java.lang.String], could not be converted to [class java.lang.Class]. Ensure that the class [TagSet] is on the
CLASSPATH. You may need to use alternate API passing in the appropriate class loader as required, or setting it on the default ConversionManager
Internal Exception: java.lang.ClassNotFoundException: TagSet
at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConvertedToClass(ConversionException.java:87)
[I know that TYPE(t) above is giving a java.lang.Class back ok, because if I provoke a construction error by using a constructor TagSetView(String,Long,String)
I get another error message saying that it expects TagSetView.<init>(java.lang.Class, java.lang.Long, java.lang.String).]
I don't see why it could not find the class TagSet. It is a complete Netbeans+Glassfish Java EE6 Web application.
The entities are surely already available to the container-managed transaction-scoped entity manager when
the query is executed.
Very grateful for help on this, as although I can get more limited projection queries working,
I really need to get at the entity class of each row (not so much in this trivial TagSet case,
which is a test run, but in other more complex domain entity class cases, where I need
to provide information on the class of an object alongside information on the object,
where here the actual entity object is in fact represented by the minimal View DTO).
thanks,
Webel IT Australia
|
|
| | |
Re: TYPE() fails in projection query result: EclipseLink ConversionException [message #713742 is a reply to message #713503] |
Mon, 08 August 2011 20:07   |
Eclipse User |
|
|
|
@james who wrote:
Quote:
Ah, this is because the TYPE is the value stored in the type column, which is only the entity name, and does not contain the package.
I tried this already, i.e. I tried a constructor expression that feeds a constructor with a String argument, and it fails, as explained in my initial post, requesting a constructor with a java.lang.Class argument. I wrote:
Quote:
know that TYPE(t) above is giving a java.lang.Class back ok, because if I provoke a construction error by using a constructor TagSetView(String,Long,String) I get another error message saying that it expects TagSetView.<init>(java.lang.Class, java.lang.Long, java.lang.String).
In fact if I use a constructor with argument type Object I still get the same ConversionException error I initially reported.
In any case, the entity name is not the same thing as the type, although it defaults to the simple class name of the type. So why, if it returns the entity name, would it be called TYPE() ?
The evidence above suggests that TYPE() returns a Class object. Also, in the Criteria API, the type() method returns a Class.
On the other hand, TYPE can be used in comparison expressions without a fully qualified class name, indeed comparing with the entity name. Example from Pro JPA2 p.262:
SELECT p.name, CASE WHEN TYPE(p) = DesignProject THEN 'Development' ..
Here 'DesignProeject' is clearly an entity name.
So why then does a constructor expression to accept a TYPE() using a String fail with a request for a java.lang.Class ?
Can somebody please provide a functioning example of TYPE() being used in a projection query ?
[Updated on: Mon, 08 August 2011 20:34] by Moderator
|
|
| |
Re: TYPE() fails in projection query result: EclipseLink ConversionException [message #713753 is a reply to message #713752] |
Mon, 08 August 2011 21:04   |
Eclipse User |
|
|
|
From Pro JPA p.263, Criteria API type() is for comparison with Class, not with entity name, where below cb is a CriteriaBuilder:
CriteriaQuery<Object[]> c = cb.createQuery(Object[].class);
Root<Project> project = c.from(Project.class);
c.multiselect(project.get("name"),
cb.selectCase(),
.when(cb.equal(project.type(), DesignProject.class),"Development")
..
This is clearly not an entity name, but is compared in the book with p.262:
SELECT p.name,
CASE when TYPE(p) = DesignProject THEN 'Development'
in the above DesignProject would seem to be an entity name (by default, but not necessarily, the simple name of the entity class).
|
|
| | |
Re: TYPE() fails in projection query result: EclipseLink ConversionException [message #713816 is a reply to message #713799] |
Tue, 09 August 2011 02:21   |
Eclipse User |
|
|
|
@james
Quote:
Does the same query work in JSE (outside of Glassfish)
I create a Java SE application corresponding to the Employee, EmployeeService, EmployeeTest example p.28 - 30 Pro JPA2.
I confirmed it runs ok.
I then adapted it as shown below to also perform a projection query into a construction expression for an EmployeeDTO thus,
with the first run targetting a Class as expected result from TYPE(e):
package examples.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/** Adapted from Pro JPA2 p.20
*
*/
@Entity
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
public Employee() {}
public Employee(long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private long salary;
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Employee)) {
return false;
}
Employee other = (Employee) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "examples.model.Employee[ id=" + id + " ]";
}
}
public class EmployeeDTO {
private Long id;
public Long getId() {
return id;
}
private String name;
public String getName() {
return name;
}
private Class entityClass;
public Class getEntityClass() {
return entityClass;
}
private String entityName;
public String getEntityName() {
return entityName;
}
public EmployeeDTO(Class entityClass, Long id, String name) {
this.entityClass = entityClass;
this.id = id;
this.name = name;
}
/*
public EmployeeDTO(String entityName, Long id, String name) {
this.entityName = entityName;
this.id = id;
this.name = name;
}*/
@Override
public String toString() {
return "EmployeeDTO[ id=" + id + " ] [ name="+name+"] [ entityName="+entityName+"] [ entityClass="+entityClass+"]";
}
}
package examples.application;
import examples.model.Employee;
import examples.model.EmployeeDTO;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
/** Adapted from Pro JPA2 p.28-29
*
* Not container-managed.
*
*/
public class EmployeeService {
protected EntityManager em;
public EmployeeService(EntityManager em) {
this.em = em;
}
//public Employee createEmployee(int id, String name, long salary) {
public Employee createEmployee(long id, String name, long salary) {
Employee emp = new Employee(id);
emp.setName(name);
emp.setSalary(salary);
em.persist(emp);
return emp;
}
public void removeEmployee(long id) {
Employee emp = findEmployee(id);
if (emp != null) {
em.remove(emp);
}
}
public Employee findEmployee(long id) {
return em.find(Employee.class,id);
}
public Employee raiseEmployeeSalary(long id, long raise) {
Employee emp = em.find(Employee.class,id);
if (emp != null) {
emp.setSalary(emp.getSalary()+raise);
}
return emp;
}
public List<Employee> findAllEmployees() {
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e", Employee.class);
return query.getResultList();
}
public List<EmployeeDTO> findAllEmployeeDTOs() {
return em.createQuery(
"SELECT NEW examples.model.EmployeeDTO(TYPE(e),e.id,e.name) "+
"FROM Employee e "+
"ORDER BY e.name",
EmployeeDTO.class)
.getResultList();
}
}
/** Java SE application, no container.
* Adapted from Pro JPA2 p.20
*/
public class EmployeeTest {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPAexample-ejbPU");
EntityManager em = emf.createEntityManager();
EmployeeService service = new EmployeeService(em);
long id = 158;
//create and persist
em.getTransaction().begin();
Employee emp = service.createEmployee(id, "John Doe", 45000);
em.getTransaction().commit();
System.out.println("Persisted "+emp);
//find
emp = service.findEmployee(id);
System.out.println("Found "+emp);
//find all
List<Employee> emps = service.findAllEmployees();
for (Employee e: emps)
System.out.println("Found employee: " +e);
//find all DTOs
List<EmployeeDTO> empDTOs = service.findAllEmployeeDTOs();
for (EmployeeDTO eDTO: empDTOs)
System.out.println("Found employee DTO: " +eDTO);
//update
em.getTransaction().begin();
service.raiseEmployeeSalary(id, 1000);
em.getTransaction().commit();
System.out.println("Updated "+emp);
//remove
em.getTransaction().begin();
service.removeEmployee(id);
em.getTransaction().commit();
System.out.println("Removed employee "+id);
//close
em.close();
emf.close();
}
}
This failed with the following error:
Persisted examples.model.Employee[ id=158 ]
Found examples.model.Employee[ id=158 ]
Found employee: examples.model.Employee[ id=158 ]
Exception in thread "main" Local Exception Stack:
Exception [EclipseLink-6093] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.QueryException
Exception Description: Invalid Type Expression on [examples.model.Employee]. The class does not have a descriptor, or a descriptor that does not use inheritance or uses a ClassExctractor for inheritance
at org.eclipse.persistence.exceptions.QueryException.invalidTypeExpression(QueryException.java:717)
at org.eclipse.persistence.internal.expressions.ClassTypeExpression.validateNode(ClassTypeExpression.java:101)
at org.eclipse.persistence.expressions.Expression.normalize(Expression.java:2962)
at org.eclipse.persistence.internal.expressions.DataExpression.normalize(DataExpression.java:342)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1311)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:560)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:506)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareReportQuerySelectAllRows(ExpressionQueryMechanism.java:1542)
at org.eclipse.persistence.queries.ReportQuery.prepareSelectAllRows(ReportQuery.java:1298)
at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:628)
at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1047)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:577)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:824)
at org.eclipse.persistence.queries.DatabaseQuery.prepareCall(DatabaseQuery.java:1690)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:271)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:187)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:139)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:123)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1376)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1398)
at examples.application.EmployeeService.findAllEmployeeDTOs(EmployeeService.java:63)
at examples.application.EmployeeTest.main(EmployeeTest.java:44)
Java Result: 1
I then changed the constructor of EmployeeDTO to only accept a String entity name:
public EmployeeDTO(String entityName, Long id, String name) {
this.entityName = entityName;
this.id = id;
this.name = name;
}
And I get an error similar to the one that started this thread:
Persisted examples.model.Employee[ id=158 ]
Found examples.model.Employee[ id=158 ]
Found employee: examples.model.Employee[ id=158 ]
Exception in thread "main" Local Exception Stack:
Exception [EclipseLink-6137] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.QueryException
Exception Description: An Exception was thrown while executing a ReportQuery with a constructor expression: java.lang.NoSuchMethodException: examples.model.EmployeeDTO.<init>(java.lang.Class, java.lang.Long, java.lang.String)
Query: ReportQuery(referenceClass=Employee jpql="SELECT NEW examples.model.EmployeeDTO(TYPE(e),e.id,e.name) FROM Employee e ORDER BY e.name")
at org.eclipse.persistence.exceptions.QueryException.exceptionWhileUsingConstructorExpression(QueryException.java:491)
at org.eclipse.persistence.queries.ConstructorReportItem.initialize(ConstructorReportItem.java:188)
at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1035)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:577)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:824)
at org.eclipse.persistence.queries.DatabaseQuery.prepareCall(DatabaseQuery.java:1690)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:271)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:187)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:139)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:123)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1376)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1398)
at examples.application.EmployeeService.findAllEmployeeDTOs(EmployeeService.java:63)
at examples.application.EmployeeTest.main(EmployeeTest.java:44)
Java Result: 1
Note once again that is seems to want a Class: EmployeeDTO.<init>(java.lang.Class, java.lang.Long, java.lang.String) (but when I use that constructor is also fails as shown above).
To be sure I tried the projection query without the TYPE(e) and into a constructor EmployeeDTO(Long id, String name) and it worked just fine.
There is something strange happening when TYPE() is used in projection queries in combination with constructor expressions.
|
|
| |
(no subject) [message #713823 is a reply to message #713800] |
Tue, 09 August 2011 02:21   |
Eclipse User |
|
|
|
@james
Quote:
> Does the same query work in JSE (outside of Glassfish)
I create a Java SE application corresponding to the Employee, EmployeeService, EmployeeTest example p.28 - 30 Pro JPA2.
I confirmed it runs ok.
I then adapted it as shown below to also perform a projection query into a construction expression for an EmployeeDTO thus,
with the first run targetting a Class as expected result from TYPE(e):
package examples.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/** Adapted from Pro JPA2 p.20
*
*/
@Entity
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
public Employee() {}
public Employee(long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private long salary;
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Employee)) {
return false;
}
Employee other = (Employee) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "examples.model.Employee[ id=" + id + " ]";
}
}
public class EmployeeDTO {
private Long id;
public Long getId() {
return id;
}
private String name;
public String getName() {
return name;
}
private Class entityClass;
public Class getEntityClass() {
return entityClass;
}
private String entityName;
public String getEntityName() {
return entityName;
}
public EmployeeDTO(Class entityClass, Long id, String name) {
this.entityClass = entityClass;
this.id = id;
this.name = name;
}
/*
public EmployeeDTO(String entityName, Long id, String name) {
this.entityName = entityName;
this.id = id;
this.name = name;
}*/
@Override
public String toString() {
return "EmployeeDTO[ id=" + id + " ] [ name="+name+"] [ entityName="+entityName+"] [ entityClass="+entityClass+"]";
}
}
package examples.application;
import examples.model.Employee;
import examples.model.EmployeeDTO;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
/** Adapted from Pro JPA2 p.28-29
*
* Not container-managed.
*
*/
public class EmployeeService {
protected EntityManager em;
public EmployeeService(EntityManager em) {
this.em = em;
}
//public Employee createEmployee(int id, String name, long salary) {
public Employee createEmployee(long id, String name, long salary) {
Employee emp = new Employee(id);
emp.setName(name);
emp.setSalary(salary);
em.persist(emp);
return emp;
}
public void removeEmployee(long id) {
Employee emp = findEmployee(id);
if (emp != null) {
em.remove(emp);
}
}
public Employee findEmployee(long id) {
return em.find(Employee.class,id);
}
public Employee raiseEmployeeSalary(long id, long raise) {
Employee emp = em.find(Employee.class,id);
if (emp != null) {
emp.setSalary(emp.getSalary()+raise);
}
return emp;
}
public List<Employee> findAllEmployees() {
TypedQuery<Employee> query = em.createQuery(
"SELECT e FROM Employee e", Employee.class);
return query.getResultList();
}
public List<EmployeeDTO> findAllEmployeeDTOs() {
return em.createQuery(
"SELECT NEW examples.model.EmployeeDTO(TYPE(e),e.id,e.name) "+
"FROM Employee e "+
"ORDER BY e.name",
EmployeeDTO.class)
.getResultList();
}
}
/** Java SE application, no container.
* Adapted from Pro JPA2 p.20
*/
public class EmployeeTest {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPAexample-ejbPU");
EntityManager em = emf.createEntityManager();
EmployeeService service = new EmployeeService(em);
long id = 158;
//create and persist
em.getTransaction().begin();
Employee emp = service.createEmployee(id, "John Doe", 45000);
em.getTransaction().commit();
System.out.println("Persisted "+emp);
//find
emp = service.findEmployee(id);
System.out.println("Found "+emp);
//find all
List<Employee> emps = service.findAllEmployees();
for (Employee e: emps)
System.out.println("Found employee: " +e);
//find all DTOs
List<EmployeeDTO> empDTOs = service.findAllEmployeeDTOs();
for (EmployeeDTO eDTO: empDTOs)
System.out.println("Found employee DTO: " +eDTO);
//update
em.getTransaction().begin();
service.raiseEmployeeSalary(id, 1000);
em.getTransaction().commit();
System.out.println("Updated "+emp);
//remove
em.getTransaction().begin();
service.removeEmployee(id);
em.getTransaction().commit();
System.out.println("Removed employee "+id);
//close
em.close();
emf.close();
}
}
This failed with the following error:
Persisted examples.model.Employee[ id=158 ]
Found examples.model.Employee[ id=158 ]
Found employee: examples.model.Employee[ id=158 ]
Exception in thread "main" Local Exception Stack:
Exception [EclipseLink-6093] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.QueryException
Exception Description: Invalid Type Expression on [examples.model.Employee]. The class does not have a descriptor, or a descriptor that does not use inheritance or uses a ClassExctractor for inheritance
at org.eclipse.persistence.exceptions.QueryException.invalidTypeExpression(QueryException.java:717)
at org.eclipse.persistence.internal.expressions.ClassTypeExpression.validateNode(ClassTypeExpression.java:101)
at org.eclipse.persistence.expressions.Expression.normalize(Expression.java:2962)
at org.eclipse.persistence.internal.expressions.DataExpression.normalize(DataExpression.java:342)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1311)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:560)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:506)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareReportQuerySelectAllRows(ExpressionQueryMechanism.java:1542)
at org.eclipse.persistence.queries.ReportQuery.prepareSelectAllRows(ReportQuery.java:1298)
at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:628)
at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1047)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:577)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:824)
at org.eclipse.persistence.queries.DatabaseQuery.prepareCall(DatabaseQuery.java:1690)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:271)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:187)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:139)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:123)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1376)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1398)
at examples.application.EmployeeService.findAllEmployeeDTOs(EmployeeService.java:63)
at examples.application.EmployeeTest.main(EmployeeTest.java:44)
Java Result: 1
I then changed the constructor of EmployeeDTO to only accept a String entity name:
public EmployeeDTO(String entityName, Long id, String name) {
this.entityName = entityName;
this.id = id;
this.name = name;
}
And I get an error similar to the one that started this thread:
Persisted examples.model.Employee[ id=158 ]
Found examples.model.Employee[ id=158 ]
Found employee: examples.model.Employee[ id=158 ]
Exception in thread "main" Local Exception Stack:
Exception [EclipseLink-6137] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.QueryException
Exception Description: An Exception was thrown while executing a ReportQuery with a constructor expression: java.lang.NoSuchMethodException: examples.model.EmployeeDTO.<init>(java.lang.Class, java.lang.Long, java.lang.String)
Query: ReportQuery(referenceClass=Employee jpql="SELECT NEW examples.model.EmployeeDTO(TYPE(e),e.id,e.name) FROM Employee e ORDER BY e.name")
at org.eclipse.persistence.exceptions.QueryException.exceptionWhileUsingConstructorExpression(QueryException.java:491)
at org.eclipse.persistence.queries.ConstructorReportItem.initialize(ConstructorReportItem.java:188)
at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1035)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:577)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:824)
at org.eclipse.persistence.queries.DatabaseQuery.prepareCall(DatabaseQuery.java:1690)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:271)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:187)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:139)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:123)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1376)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1398)
at examples.application.EmployeeService.findAllEmployeeDTOs(EmployeeService.java:63)
at examples.application.EmployeeTest.main(EmployeeTest.java:44)
Java Result: 1
Note once again that is seems to want a Class: EmployeeDTO.<init>(java.lang.Class, java.lang.Long, java.lang.String) (but when I use that constructor is also fails as shown above).
To be sure I tried the projection query without the TYPE(e) and into a constructor EmployeeDTO(Long id, String name) and it worked just fine.
There is something strange happening when TYPE() is used in projection queries in combination with constructor expressions.
|
|
| | | |
Re: (no subject) [message #714983 is a reply to message #714841] |
Thu, 11 August 2011 21:21   |
Eclipse User |
|
|
|
@Chris
Quote:
Type can only be used on entities with inheritance and a field defining their type.
Regarding my non-container mini-test thanks for altering my to this flaw in my single Employee test. I introduced a base Element with the 'id' and 'name' properties, leaving Employee with the 'salary', tables were created with a DTYPE column, and I tried extracting the TYPE() into a project query without a constructor expression first, to diagnose what TYPE() returns:
From EmployeeService:
public List findAllEmployeeProjectionObjects() {
return em.createQuery(
"SELECT TYPE(e), e.id,e.name "+
"FROM Employee e "+
"ORDER BY e.name")
.getResultList();
}
From EmployeeTest:
//find all projection query as Object[]
List result = service.findAllEmployeeProjectionObjects();
int count=0;
for (Iterator i = result.iterator(); i.hasNext();) {
Object[] values = (Object[]) i.next();
System.out.println(++count + ": "+values[0]+", "+values[1]+", "+values[2]);
}
Runs fine (without using constructor expression into my EmployeeDTO:
Persisted examples.model.Employee[ id=158, name=John Doe, salary= 45000 ]
Found examples.model.Employee[ id=158, name=John Doe, salary= 45000 ]
Found employee: examples.model.Employee[ id=158, name=John Doe, salary= 45000 ]
1: class examples.model.Employee, 158, John Doe
This clearly shows a Class object 'class examples.model.Employee' returned from the TYPE(e).
I then tried it with the projection query into a constructor expression. From EmployeeService:
public List<EmployeeDTO> findAllEmployeeDTOs() {
return em.createQuery(
"SELECT NEW examples.model.EmployeeDTO(TYPE(e),e.id,e.name) "+
"FROM Employee e "+
"ORDER BY e.name",
EmployeeDTO.class)
.getResultList();
}
(I omit the EmployeeDTO but it exists.) And in EmployeeTest:
List<EmployeeDTO> empDTOs = service.findAllEmployeeDTOs();
But I get the same error that instigated this thread:
Persisted examples.model.Employee[ id=158, name=John Doe, salary= 45000 ]
Found examples.model.Employee[ id=158, name=John Doe, salary= 45000 ]
Found employee: examples.model.Employee[ id=158, name=John Doe, salary= 45000 ]
[EL Warning]: 2011-08-12 11:16:25.184--UnitOfWork(1453807415)--Exception [EclipseLink-3007] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.ConversionException
Exception in thread "main" Local Exception Stack:
Exception Description: The object [Employee], of class [class java.lang.String], could not be converted to [class java.lang.Class]. Ensure that the class [Employee] is on the CLASSPATH. You may need to use alternate API passing in the appropriate class loader as required, or setting it on the default ConversionManager
Internal Exception: java.lang.ClassNotFoundException: Employee
Exception [EclipseLink-3007] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [Employee], of class [class java.lang.String], could not be converted to [class java.lang.Class]. Ensure that the class [Employee] is on the CLASSPATH. You may need to use alternate API passing in the appropriate class loader as required, or setting it on the default ConversionManager
Internal Exception: java.lang.ClassNotFoundException: Employee
at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConvertedToClass(ConversionException.java:87)
at org.eclipse.persistence.internal.helper.ConversionManager.convertObjectToClass(ConversionManager.java:440)
at org.eclipse.persistence.internal.helper.ConversionManager.convertObject(ConversionManager.java:141)
at org.eclipse.persistence.queries.ReportQueryResult.buildResult(ReportQueryResult.java:108)
at org.eclipse.persistence.queries.ReportQueryResult.<init>(ReportQueryResult.java:76)
at org.eclipse.persistence.queries.ReportQuery.buildObject(ReportQuery.java:594)
at org.eclipse.persistence.queries.ReportQuery.buildObjects(ReportQuery.java:645)
at org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:841)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:808)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1040)
at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:383)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1126)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2842)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1521)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1503)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1477)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:484)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getResultList(EJBQueryImpl.java:741)
at examples.application.EmployeeService.findAllEmployeeDTOs(EmployeeService.java:63)
at examples.application.EmployeeTest.main(EmployeeTest.java:50)
Caused by: java.lang.ClassNotFoundException: Employee
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at org.eclipse.persistence.internal.helper.ConversionManager.convertObjectToClass(ConversionManager.java:437)
... 18 more
So whether I use a container (Glassfish) or not it fails with the same error.
@james Testing this outside the container was a good idea, I've also learnt something that might be useful on other projects, namely how to test queries outside a container.
|
|
|
Re: (no subject) [message #714991 is a reply to message #714841] |
Thu, 11 August 2011 22:01  |
Eclipse User |
|
|
|
I have reported this as bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=354572
I've since realized that a workaround exists for me, namely I can perform the projection query into a List<Object[]> then extract the necessary bits and feed them into my EmployeeDTO constructor thus:
/** Workaround for bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=354572
*
* Since projection query with TYPE() into constructor expression fails,
* perform projection query into interim List<Object[]> then iterate over
* result to extract List<EmployeeDTO>
*/
public List<EmployeeDTO> findAllEmployeeDTOsViaProjectionObjects() {
List result = em.createQuery(
"SELECT TYPE(e), e.id,e.name "+
"FROM Employee e "+
"ORDER BY e.name")
.getResultList();
List<EmployeeDTO> dtos = new ArrayList<EmployeeDTO>();
for (Iterator i = result.iterator(); i.hasNext();) {
Object[] values = (Object[]) i.next();
EmployeeDTO dto = new EmployeeDTO((Class)values[0],(Long)values[1],(String)values[2]);
dtos.add(dto);
}
return dtos;
}
|
|
|
(no subject) [message #714993 is a reply to message #714841] |
Thu, 11 August 2011 22:01  |
Eclipse User |
|
|
|
I have reported this as bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=354572
I've since realized that a workaround exists for me, namely I can perform the projection query into a List<Object[]> then extract the necessary bits and feed them into my EmployeeDTO constructor thus:
/** Workaround for bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=354572
*
* Since projection query with TYPE() into constructor expression fails,
* perform projection query into interim List<Object[]> then iterate over
* result to extract List<EmployeeDTO>
*/
public List<EmployeeDTO> findAllEmployeeDTOsViaProjectionObjects() {
List result = em.createQuery(
"SELECT TYPE(e), e.id,e.name "+
"FROM Employee e "+
"ORDER BY e.name")
.getResultList();
List<EmployeeDTO> dtos = new ArrayList<EmployeeDTO>();
for (Iterator i = result.iterator(); i.hasNext();) {
Object[] values = (Object[]) i.next();
EmployeeDTO dto = new EmployeeDTO((Class)values[0],(Long)values[1],(String)values[2]);
dtos.add(dto);
}
return dtos;
}
|
|
|
Goto Forum:
Current Time: Tue Jul 22 17:46:48 EDT 2025
Powered by FUDForum. Page generated in 0.10161 seconds
|