I'm blocked on this problem for many hours and I don't understand the problem as it works fine with another entity of my project. I created a Java EE project with Glassfish 4, JPA 2 and EJB 3 in Eclipse IDE. I'm using a mysql database for storing.
I created a entity bean named Company and a DAO to manage it. I did all it needs to work and it works well. The problem is that I did exactly the same thing for another entity bean, called Newsletter, but this one doesn't work. Java throws an EJBException, telling me that the abstract schema is unknown, but it exists in the DB. The tables company and newsletter are in the same db, so I used the same persistence unit for both of them.
Some questions I found on Google or here are solved by adding the class to the persitence-unit and I did it, but it still throws me an exception.
Here is my NEWSLETTER table:
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| idNewsletter | int(11) | NO | PRI | NULL | auto_increment |
| firstname | varchar(100) | NO | | NULL | |
| lastname | varchar(100) | NO | | NULL | |
| email | varchar(255) | NO | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
My bean Newsletter:
@Entity
public class Newsletter {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idNewsletter;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
@Column(name="email")
private String email;
}
Here is my persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="2lifedb_PU" transaction-type="JTA">
<jta-data-source>jdbc/bonecp_resource</jta-data-source>
<class>com.twolife.beans.User</class>
<class>com.twolife.beans.Company</class>
<class>com.twolife.beans.Office</class>
<class>com.twolife.beans.BankDetails</class>
<class>com.twolife.beans.Logo</class>
<class>com.twolife.beans.Newsletter</class>
<properties>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
</properties>
</persistence-unit>
And the DAO class:
@Stateless
public class DAONewsletter {
private static final String SQL_SELECT_NEWSLETTER = "SELECT n FROM NEWSLETTER n WHERE n.email = :email";
@PersistenceContext(unitName="2lifedb_PU")
private EntityManager em;
public void create(Newsletter newsletter) throws DAOException {
try {
em.persist(newsletter);
} catch (Exception e) {
throw new DAOException(e);
}
}
public Newsletter find(String email) throws DAOException {
Newsletter newsletter = new Newsletter();
Query query = em.createQuery(SQL_SELECT_NEWSLETTER);
query.setParameter("email", email);
try {
newsletter = (Newsletter) query.getSingleResult();
} catch (NoResultException e) {
return null;
} catch (Exception e) {
throw new DAOException(e);
}
return newsletter;
}
}
And finally, here is the stacktrace of my exception:
Caused by: java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Problem compiling [SELECT n FROM NEWSLETTER n WHERE n.email = :email].
[14, 24] The abstract schema type 'NEWSLETTER' is unknown.
[33, 40] The state field path 'n.email' cannot be resolved to a valid type.
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1585)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.createQuery(EntityManagerWrapper.java:456)
at com.twolife.dao.DAONewsletter.find(DAONewsletter.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4695)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:630)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:582)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4667)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4655)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
... 36 more
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Problem compiling [SELECT n FROM NEWSLETTER n WHERE n.email = :email].
[14, 24] The abstract schema type 'NEWSLETTER' is unknown.
[33, 40] The state field path 'n.email' cannot be resolved to a valid type.
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildException(HermesParser.java:155)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.validate(HermesParser.java:347)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.populateQueryImp(HermesParser.java:278)
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildQuery(HermesParser.java:163)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:142)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:116)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:102)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:86)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1583)
... 60 more
If anoyone get an idea, that would be really helpful! And sorry for some english mistakes, it is not my mother language...
em.createQuery() expects a JPQL query, not a SQL query. SQL and JPQL are not the same language. SQL works with tables and columns. JPQL works with entities, fields/properties and associations. NEVER with table and column names. The syntax is similar, but different.
Your entity is named Newsletter
, but your query uses NEWSLETTER
. Class names are case sensitive.