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 08:45 |
darren Messages: 19 Registered: March 2011 Location: Sydney, Australia |
Junior Member |
|
|
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] |
Tue, 09 August 2011 00:07 |
darren Messages: 19 Registered: March 2011 Location: Sydney, Australia |
Junior Member |
|
|
@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: Tue, 09 August 2011 00:34] Report message to a moderator
|
|
| |
Re: TYPE() fails in projection query result: EclipseLink ConversionException [message #713753 is a reply to message #713752] |
Tue, 09 August 2011 01:04 |
darren Messages: 19 Registered: March 2011 Location: Sydney, Australia |
Junior Member |
|
|
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 06:21 |
darren Messages: 19 Registered: March 2011 Location: Sydney, Australia |
Junior Member |
|
|
@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 06:21 |
darren Messages: 15 Registered: July 2009 |
Junior Member |
|
|
@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 #714841 is a reply to message #714022] |
Thu, 11 August 2011 15:24 |
|
Sorry, yes there does seem to be an issue here. Either TYPE should return the real Class, or it should return the String value. Seems like it should return the Class, so should be handling this conversion differently, please log a bug for this.
It is set to a class type in ClassForInheritanceNode.applyToQuery, if you change this to pass String.class instead then it would return the String value.
James : Wiki : Book : Blog : Twitter
|
|
|
Re: (no subject) [message #714983 is a reply to message #714841] |
Fri, 12 August 2011 01:21 |
darren Messages: 19 Registered: March 2011 Location: Sydney, Australia |
Junior Member |
|
|
@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.
|
|
| | |
Goto Forum:
Current Time: Fri Sep 20 01:58:09 GMT 2024
Powered by FUDForum. Page generated in 0.04001 seconds
|