Wednesday, January 07, 2009

The Nasty JPA "Unknown abstract schema type" error

I been trying to debug the following error for days, and it drive me nuts!

The problem: JPA refuse to compile one of my NamedQuery, and throws 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 search, I conclude that JPA will throw "Unknown abstract schema type" when JPA fail locate your entity class". Most often, this type error occurs when:
  • Developer have put down database table name instead of Entity Class name in the JPA query. eg. if we have a EntityClass UserVO which map to table name users, the query "SELECT u from users u" will throw the above exception.
  • When running JPA in standalone, or not JavaEE container(such as Tomcat 5/6), they forgot to explicit list all entities class in the persistence.xml, thus JPA fail to locate the entities when compile the query.
None of above apply to my case, I have explicit listed all my entities class in the persistence.xml
and I am sure my JPA query is valid. I have tested my code with different JPA implementations, but always resulted the same error..

Here my UserVO class


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

|
|
}


If I remove the NamedQuery, my JPA able to work as expected, i.e I am able to insert, delete, and update UserVO object.
Now, to all my smart reader, can u spot what's wrong in my code? Scroll down for answer.


|
|
|
|
|
|
|

Answer: The culprit is the Entity annotation, I explicit name the UserVO entity as users, which JPA have no problem to map the UserVO to users database table, but have problem to compile the JPA Query, because it can't find the UserVO entity in the JPA context, as the suppose UserVO entity have rename to users entity by me, got it, or confuse..

To resolve this, just add a @Table annotation with the table name, as shown code below:


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

|
|
}


Cheers, Happy New Year!!!!

3 comments:

David said...

I think it'll be cleaner and simpler to just rename your "UserVO" class to "User".

Anonymous said...

I was stuck with this problem as I named the java entity class differently to the database table name (which i think is appropriate in some cases - perhaps database table names are in a different human language to your UI, or maybe named inappropriately). Thanks.

Anonymous said...

Thanks for the post
It helps me