Khoo has posted 3 posts at DZone. View Full User Profile

JPA's Nasty "Unknown abstract schema type" Error

01.13.2009
| 19730 views |
  • submit to reddit
I'd been trying to debug the following error for days, and it drove me crazy. The problem, in a nutshell, is that JPA refuses to compile one of my NamedQueries, throwing the following error:

Error compiling the query [UserVO.findByUserName: SELECT u FROM UserVO u WHERE u.name = :name].
Unknown abstract schema type [UserVO]


After numerous Google searches, I concluded that JPA will throw the "Unknown abstract schema type"  error when JPA fails to locate your entity class.  Most often, this type of error occurs when:

  • You have provided the database table name instead of the entity class name in the JPA query. For example, if you have an entity class called "UserVO", which maps to the table name "users", the query "SELECT u from users u" will throw the above exception.

  • When running JPA in standalone mode, or not in a Java EE container (such as Tomcat 5 or 6), you forget to explicitly list all entity classes in the persistence.xml file, thus causing JPA to fail to locate the entities when compiling the query.


Neither of above applied to my case. I have explicitly listed all my entity classes in the persistence.xml and I am sure my JPA query is valid. I have tested my code with different JPA implementations, but always saw the same error.

Here's my UserVO class:
@Entity(name = "users")
@NamedQuery(name = "UserVO.findByUserName",
query = "SELECT u FROM UserVO u WHERE u.name = :name")
public class UserVO extends BaseVO implements Serializable {

...
...
}


If I remove the NamedQuery, my JPA works as expected, i.e, I am able to insert, delete, and update the UserVO object.

Now, to all my smart readers, can you spot what's wrong in my code? Think about it and then scroll down for the answer...

 

 

 

 

 

 

 

 

Answer: The culprit is the Entity annotation. I explicitly named the UserVO entity "users". JPA has no problem to map the UserVO entity to the users database table. However, JPA has a problem when compiling the JPA Query: it can't find the UserVO entity in the JPA context because I have renamed the UserVO entity to users.

To resolve this, just add a @Table annotation with the table name, as shown in the code below:
@Entity
@Table(name = "users")
@NamedQuery(name = "UserVO.findByUserName",
query = "SELECT u FROM UserVO u WHERE u.name = :name")
public class UserVO extends BaseVO implements Serializable {

...
...
}

Haha, stupid me... Anyway, Happy New Year to everyone.
0
Your rating: None
Published at DZone with permission of its author, Khoo Chen Shiang.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Dist Iller replied on Tue, 2009/01/13 - 4:29pm

And the relevance this has to anything ?

 JPA is a specification, how can it do anything ?

Jabarovinsky Luke replied on Sat, 2011/11/26 - 12:18pm

I googled everywhere without a solucion for my unknow abstract schema problem. I´d like to understand more: I currently use Netbeans. I added the class Categorias and Itensdespesa at the persistence unit. I´m connected to the Derby DB. I have the following code: /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package spc01; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; import javax.persistence.Transient; /** * * @author gslima */ @Entity @Table(name = "CATEGORIAS", catalog = "", schema = "APP") @NamedQueries({ @NamedQuery(name = "Categorias.findAll", query = "SELECT c FROM Categorias c"), @NamedQuery(name = "Categorias.findByIdcat", query = "SELECT c FROM Categorias c WHERE c.idcat = :idcat"), @NamedQuery(name = "Categorias.findByNomecat", query = "SELECT c FROM Categorias c WHERE c.nomecat = :nomecat")}) public class Categorias implements Serializable { @Transient private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); private static final long serialVersionUID = 1L; @Id @Basic(optional = false) @Column(name = "IDCAT") private Integer idcat; @Basic(optional = false) @Column(name = "NOMECAT") private String nomecat; public Categorias() { } public Categorias(Integer idcat) { this.idcat = idcat; } public Categorias(Integer idcat, String nomecat) { this.idcat = idcat; this.nomecat = nomecat; } public Integer getIdcat() { return idcat; } public void setIdcat(Integer idcat) { Integer oldIdcat = this.idcat; this.idcat = idcat; changeSupport.firePropertyChange("idcat", oldIdcat, idcat); } public String getNomecat() { return nomecat; } public void setNomecat(String nomecat) { String oldNomecat = this.nomecat; this.nomecat = nomecat; changeSupport.firePropertyChange("nomecat", oldNomecat, nomecat); } @Override public int hashCode() { int hash = 0; hash += (idcat != null ? idcat.hashCode() : 0); return hash; } @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 Categorias)) { return false; } Categorias other = (Categorias) object; if ((this.idcat == null && other.idcat != null) || (this.idcat != null && !this.idcat.equals(other.idcat))) { return false; } return true; } @Override public String toString() { return "spc01.Categorias[ idcat=" + idcat + " ]"; } public void addPropertyChangeListener(PropertyChangeListener listener) { changeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { changeSupport.removePropertyChangeListener(listener); } } And the class Itensdespesa /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package spc01; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; import javax.persistence.Transient; /** * * @author gslima */ @Entity @Table(name = "ITENSDESPESA", catalog = "", schema = "APP") @NamedQueries({ @NamedQuery(name = "Itensdespesa.findAll", query = "SELECT i FROM Itensdespesa i"), @NamedQuery(name = "Itensdespesa.findByIddesp", query = "SELECT i FROM Itensdespesa i WHERE i.iddesp = :iddesp"), @NamedQuery(name = "Itensdespesa.findByNomedesp", query = "SELECT i FROM Itensdespesa i WHERE i.nomedesp = :nomedesp"), @NamedQuery(name = "Itensdespesa.findByValordesp", query = "SELECT i FROM Itensdespesa i WHERE i.valordesp = :valordesp"), @NamedQuery(name = "Itensdespesa.findByAnodesp", query = "SELECT i FROM Itensdespesa i WHERE i.anodesp = :anodesp"), @NamedQuery(name = "Itensdespesa.findByMes", query = "SELECT i FROM Itensdespesa i WHERE i.mes = :mes"), @NamedQuery(name = "Itensdespesa.findByAtividade", query = "SELECT i FROM Itensdespesa i WHERE i.atividade = :atividade"), @NamedQuery(name = "Itensdespesa.findByVisto", query = "SELECT i FROM Itensdespesa i WHERE i.visto = :visto"), @NamedQuery(name = "Itensdespesa.findByIdcat", query = "SELECT i FROM Itensdespesa i WHERE i.idcat = :idcat"), @NamedQuery(name = "Itensdespesa.findByIdsubcat", query = "SELECT i FROM Itensdespesa i WHERE i.idsubcat = :idsubcat"), @NamedQuery(name = "Itensdespesa.findByPrestid", query = "SELECT i FROM Itensdespesa i WHERE i.prestid = :prestid")}) public class Itensdespesa implements Serializable { @Transient private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); private static final long serialVersionUID = 1L; @Id @Basic(optional = false) @Column(name = "IDDESP") private Long iddesp; @Column(name = "NOMEDESP") private String nomedesp; @Basic(optional = false) @Column(name = "VALORDESP") private long valordesp; @Basic(optional = false) @Column(name = "ANODESP") private int anodesp; @Column(name = "MES") private String mes; @Column(name = "ATIVIDADE") private String atividade; @Column(name = "VISTO") private String visto; @Column(name = "IDCAT") private Integer idcat; @Column(name = "IDSUBCAT") private Integer idsubcat; @Column(name = "PRESTID") private Integer prestid; public Itensdespesa() { } public Itensdespesa(Long iddesp) { this.iddesp = iddesp; } public Itensdespesa(Long iddesp, long valordesp, int anodesp) { this.iddesp = iddesp; this.valordesp = valordesp; this.anodesp = anodesp; } public Long getIddesp() { return iddesp; } public void setIddesp(Long iddesp) { Long oldIddesp = this.iddesp; this.iddesp = iddesp; changeSupport.firePropertyChange("iddesp", oldIddesp, iddesp); } public String getNomedesp() { return nomedesp; } public void setNomedesp(String nomedesp) { String oldNomedesp = this.nomedesp; this.nomedesp = nomedesp; changeSupport.firePropertyChange("nomedesp", oldNomedesp, nomedesp); } public long getValordesp() { return valordesp; } public void setValordesp(long valordesp) { long oldValordesp = this.valordesp; this.valordesp = valordesp; changeSupport.firePropertyChange("valordesp", oldValordesp, valordesp); } public int getAnodesp() { return anodesp; } public void setAnodesp(int anodesp) { int oldAnodesp = this.anodesp; this.anodesp = anodesp; changeSupport.firePropertyChange("anodesp", oldAnodesp, anodesp); } public String getMes() { return mes; } public void setMes(String mes) { String oldMes = this.mes; this.mes = mes; changeSupport.firePropertyChange("mes", oldMes, mes); } public String getAtividade() { return atividade; } public void setAtividade(String atividade) { String oldAtividade = this.atividade; this.atividade = atividade; changeSupport.firePropertyChange("atividade", oldAtividade, atividade); } public String getVisto() { return visto; } public void setVisto(String visto) { String oldVisto = this.visto; this.visto = visto; changeSupport.firePropertyChange("visto", oldVisto, visto); } public Integer getIdcat() { return idcat; } public void setIdcat(Integer idcat) { Integer oldIdcat = this.idcat; this.idcat = idcat; changeSupport.firePropertyChange("idcat", oldIdcat, idcat); } public Integer getIdsubcat() { return idsubcat; } public void setIdsubcat(Integer idsubcat) { Integer oldIdsubcat = this.idsubcat; this.idsubcat = idsubcat; changeSupport.firePropertyChange("idsubcat", oldIdsubcat, idsubcat); } public Integer getPrestid() { return prestid; } public void setPrestid(Integer prestid) { Integer oldPrestid = this.prestid; this.prestid = prestid; changeSupport.firePropertyChange("prestid", oldPrestid, prestid); } @Override public int hashCode() { int hash = 0; hash += (iddesp != null ? iddesp.hashCode() : 0); return hash; } @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 Itensdespesa)) { return false; } Itensdespesa other = (Itensdespesa) object; if ((this.iddesp == null && other.iddesp != null) || (this.iddesp != null && !this.iddesp.equals(other.iddesp))) { return false; } return true; } @Override public String toString() { return "spc01.Itensdespesa[ iddesp=" + iddesp + " ]"; } public void addPropertyChangeListener(PropertyChangeListener listener) { changeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { changeSupport.removePropertyChangeListener(listener); } } SPC01View.proprieties query.query=SELECT i FROM Itensdespesa i query1.query=SELECT c FROM Categorias c I have 2 diferent tables that I want to update So, I have this class: private class SaveTask extends Task { SaveTask(org.jdesktop.application.Application app) { super(app); } @Override protected Void doInBackground() { try { entityManager.getTransaction().commit(); entityManager.getTransaction().begin(); } catch (RollbackException rex) { rex.printStackTrace(); entityManager.getTransaction().begin(); List merged = new ArrayList(list.size()); for (spc01.Itensdespesa i : list) { merged.add(entityManager.merge(i)); } list.clear(); list.addAll(merged); List merged2 = new ArrayList(list1.size()); for (spc01.Categorias i : list1) { merged2.add(entityManager.merge(i)); } list1.clear(); list1.addAll(merged2); } return null; } @Override protected void finished() { setSaveNeeded(false); } } And this class for updates private class RefreshTask extends Task { RefreshTask(org.jdesktop.application.Application app) { super(app); } @SuppressWarnings("unchecked") @Override protected Void doInBackground() { try { setProgress(0, 0, 4); setMessage("Rolling back the current changes..."); setProgress(1, 0, 4); entityManager.getTransaction().rollback(); Thread.sleep(1000L); // remove for real app setProgress(2, 0, 4); setMessage("Starting a new transaction..."); entityManager.getTransaction().begin(); Thread.sleep(500L); // remove for real app setProgress(3, 0, 4); setMessage("Fetching new data..."); java.util.Collection data = query.getResultList(); java.util.Collection data2 = query1.getResultList(); for (Object entity : data) { entityManager.refresh(entity); } for (Object entity : data2) { entityManager.refresh(entity); } Thread.sleep(1300L); // remove for real app setProgress(4, 0, 4); Thread.sleep(150L); // remove for real app list.clear(); list1.clear(); list.addAll(data); list1.addAll(data2); } catch(InterruptedException ignore) { } return null; } @Override protected void finished() { setMessage("Done."); setSaveNeeded(false); } } The queries declaration entityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory(resourceMap.getString("entityManager.persistenceUnit")).createEntityManager(); // NOI18N query = java.beans.Beans.isDesignTime() ? null : entityManager.createQuery(resourceMap.getString("query.query")); // NOI18N list = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : org.jdesktop.observablecollections.ObservableCollections.observableList(query.getResultList()); query1 = java.beans.Beans.isDesignTime() ? null : entityManager.createQuery(resourceMap.getString("query1.query")); // NOI18N list1 = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : org.jdesktop.observablecollections.ObservableCollections.observableList(query1.getResultList()); query works pretty fine if I remove query1. I can´t understand, why? WHY? Here´s the exception I get [TopLink Info]: 2011.11.26 03:04:59.843--ServerSession(17749675)--TopLink, version: Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007)) [TopLink Info]: 2011.11.26 03:05:01.325--ServerSession(17749675)--file:/C:/Users/gslima/Documents/NetBeansProjects/SPC0.1/build/classes/-SPCPU login successful Nov 26, 2011 3:05:01 PM org.jdesktop.application.Application$1 run Grave: Application class spc01.SPC01App failed to launch java.lang.IllegalArgumentException: An exception occured while creating a query in EntityManager at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerImpl.createQuery(EntityManagerImpl.java:209) at spc01.SPC01View.initComponents(SPC01View.java:358) at spc01.SPC01View.(SPC01View.java:41) at spc01.SPC01App.startup(SPC01App.java:19) at org.jdesktop.application.Application$1.run(Application.java:171) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705) at java.awt.EventQueue.access$000(EventQueue.java:101) at java.awt.EventQueue$3.run(EventQueue.java:666) at java.awt.EventQueue$3.run(EventQueue.java:664) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:675) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.awt.EventDispatchThread.run(EventDispatchThread.java:90) Caused by: Exception [TOPLINK-8034] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.EJBQLException Exception Description: Error compiling the query [SELECT c FROM Categorias c]. Unknown abstract schema type [Categorias]. at oracle.toplink.essentials.exceptions.EJBQLException.unknownAbstractSchemaType(EJBQLException.java:494) at oracle.toplink.essentials.internal.parsing.ParseTreeContext.classForSchemaName(ParseTreeContext.java:163) at oracle.toplink.essentials.internal.parsing.SelectNode.getClassOfFirstVariable(SelectNode.java:366) at oracle.toplink.essentials.internal.parsing.SelectNode.getReferenceClass(SelectNode.java:354) at oracle.toplink.essentials.internal.parsing.ParseTree.getReferenceClass(ParseTree.java:463) at oracle.toplink.essentials.internal.parsing.ParseTree.adjustReferenceClassForQuery(ParseTree.java:103) at oracle.toplink.essentials.internal.parsing.EJBQLParseTree.populateReadQueryInternal(EJBQLParseTree.java:127) at oracle.toplink.essentials.internal.parsing.EJBQLParseTree.populateQuery(EJBQLParseTree.java:108) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:219) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:189) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:153) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.(EJBQueryImpl.java:114) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.(EJBQueryImpl.java:99) at oracle.toplink.essentials.internal.ejb.cmp3.EJBQueryImpl.(EJBQueryImpl.java:86) at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerImpl.createQuery(EntityManagerImpl.java:204) ... 18 more Exception in thread "AWT-EventQueue-0" java.lang.Error: Application class spc01.SPC01App failed to launch at org.jdesktop.application.Application$1.run(Application.java:177) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705) at java.awt.EventQueue.access$000(EventQueue.java:101) at java.awt.EventQueue$3.run(EventQueue.java:666) at java.awt.EventQueue$3.run(EventQueue.java:664) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:675) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.awt.EventDispatchThread.run(EventDispatchThread.java:90) Caused by: java.lang.IllegalArgumentException: An exception occured while creating a query in EntityManager at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerImpl.createQuery(EntityManagerImpl.java:209) at spc01.SPC01View.initComponents(SPC01View.java:358) at spc01.SPC01View.(SPC01View.java:41) at spc01.SPC01App.startup(SPC01App.java:19) at org.jdesktop.application.Application$1.run(Application.java:171) ... 14 more Caused by: Exception [TOPLINK-8034] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.EJBQLException Exception Description: Error compiling the query [SELECT c FROM Categorias c]. Unknown abstract schema type [Categorias]. at oracle.toplink.essentials.exceptions.EJBQLException.unknownAbstractSchemaType(EJBQLException.java:494) at oracle.toplink.essentials.internal.parsing.ParseTreeContext.classForSchemaName(ParseTreeContext.java:163) at oracle.toplink.essentials.internal.parsing.SelectNode.getClassOfFirstVariable(SelectNode.java:366) at oracle.toplink.essentials.internal.parsing.SelectNode.getReferenceClass(SelectNode.java:354) at oracle.toplink.essentials.internal.parsing.ParseTree.getReferenceClass(ParseTree.java:463) at oracle.toplink.essentials.internal.parsing.ParseTree.adjustReferenceClassForQuery(ParseTree.java:103) at oracle.toplink.essentials.internal.parsing.EJBQLParseTree.populateReadQueryInternal(EJBQLParseTree.java:127) at oracle.toplink.essentials.internal.parsing.EJBQLParseTree.populateQuery(EJBQLParseTree.java:108) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:219) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:189) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:153) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.(EJBQueryImpl.java:114) at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.(EJBQueryImpl.java:99) at oracle.toplink.essentials.internal.ejb.cmp3.EJBQueryImpl.(EJBQueryImpl.java:86) at oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerImpl.createQuery(EntityManagerImpl.java:204) ... 18 more CONSTRUÍDO COM SUCESSO (tempo total: 9 segundos)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.