David,
This link helped a lot. The info is very clear and brief. Thank you !
I was able to fix this by injecting entityManagerFactory. I still
don't understand many of the internals, but it's ok for now.
This modification allowed me to persist a new object, but I am unable
to delete objects. It seems the issue with JPA.
Here's the working code for creating a new object, in case anyone
faces similar issue:
@PersistenceUnit(unitName = "Testing")
private EntityManagerFactory factory;
@Override
public Restaurant create(Restaurant obj)
{
EntityManager em = factory.createEntityManager();
EntityTransaction tx = em.getTransaction();
try
{
tx.begin();
obj = em.merge(obj);
em.persist(obj);
tx.commit();
} catch (Exception e)
{
logger.error("Can not create " + obj);
logger.error("Exception", e);
}
return obj;
}
The code that's failing:
@Override
public void delete(Restaurant obj)
{
EntityManager em = factory.createEntityManager();
EntityTransaction tx = em.getTransaction();
try
{
tx.begin();
obj = em.merge(obj);
em.remove(obj);
em.flush();
tx.commit();
} catch (Exception e)
{
logger.error("Can not create " + obj, e);
}
}
The exception I am getting is:
ERROR - Can not create
org.apache.openjpa.enhance.ws$mansour$entities$restaurant$pcsubcl...@2dd7e4d6
<openjpa-1.2.1-r752877:753278 nonfatal general error>
org.apache.openjpa.persistence.PersistenceException: Unknown column
't0.ENTREE_ID' in 'where clause' {prepstmnt 1323538699 SELECT t0.id,
t0.name, t0.vegetarian FROM Entree t0 WHERE t0.ENTREE_ID = ?
[params=(long) 4]} [code=1054, state=42S22]
at
org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4232)
at
org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4197)
at
org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:102)
at
org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:88)
at
org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:64)
at
org.apache.openjpa.jdbc.kernel.JDBCStoreManager.load(JDBCStoreManager.java:694)
......
Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: Unknown
column 't0.ENTREE_ID' in 'where clause' {prepstmnt 1323538699 SELECT
t0.id, t0.name, t0.vegetarian FROM Entree t0 WHERE t0.ENTREE_ID = ?
[params=(long) 4]} [code=1054, state=42S22]
at
org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:192)
at
org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.access$700(LoggingConnectionDecorator.java:57)
at
org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.executeQuery(LoggingConnectionDecorator.java:852)
at
org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:262)
at
org.apache.openjpa.jdbc.kernel.JDBCStoreManager$CancelPreparedStatement.executeQuery(JDBCStoreManager.java:1595)
at
org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:252)
at
org.apache.openjpa.jdbc.sql.SelectImpl.executeQuery(SelectImpl.java:496)
I borrowed the entities for testing from
http://blog.springsource.com/2006/05/30/getting-started-with-jpa-in-spring-20/
The wiered thing, This test is working fine when using spring and
injecting hibernate. What I need to do know, it to replace openJPA
with hibernate or eclipseLink.
But, I don't want to set any properties for a specific jpa provider in
my persistence.xml. Is there a way to do this when initializing the
container? I mean, here'e my JUnit setup and I want to add hibernate
or eclipse link instead of, openJPA. This will help me better narrow
down the issue.
@BeforeClass
public static void setUpBeforeClass() throws Exception
{
DBSetup.runDbUnitSetup();
logger.warn("Strating testing using OpenEJB");
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");
properties.put("openEjbDatabase", "new://Resource?type=DataSource");
properties.put("openEjbDatabase.JdbcDriver", "com.mysql.jdbc.Driver");
properties.put("openEjbDatabase.JdbcUrl",
"jdbc:mysql://neptune:3306/dbtest");
properties.put("openEjbDatabase.UserName", "sa");
properties.put("openEjbDatabase.PassWord", "");
context = new InitialContext(properties);
Object obj = context.lookup("RestaurantDao3Local");
dao = (IDao) obj;
}
What do I need to add, to use hibernate/toplink/eclipselink instead of
openJPA ?
On Thu, Dec 17, 2009 at 6:14 AM, David Blevins <[email protected]> wrote:
> Hi Mansour,
>
> Seems like you may have a mix of problems. Check out this doc which
> attempts to clarify JPA usage.
>
> http://openejb.apache.org/3.0/jpa-concepts.html
>
> -David
>
> On Dec 16, 2009, at 4:46 AM, Mansour Al Akeel wrote:
>
>> I do have some dao working with spring and tested them as pojos. I am
>> porting them to stateless beans. I am using User transaction (bean
>> managed transaction).
>> Following the example of entityManager injection :
>>
>> public class RestaurantDaoTest3 extends AbstractRestaurantDaoTest {
>>
>> private static Context context;
>>
>> @BeforeClass
>> public static void setUpBeforeClass() throws Exception
>> {
>> DBSetup.runDbUnitSetup();
>> logger.warn("Strating testing using OpenEJB");
>> Properties properties = new Properties();
>> properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
>> "org.apache.openejb.client.LocalInitialContextFactory");
>> properties.put("openEjbDatabase",
>> "new://Resource?type=DataSource");
>> properties.put("openEjbDatabase.JdbcDriver",
>> "com.mysql.jdbc.Driver");
>> properties.put("openEjbDatabase.JdbcUrl",
>> "jdbc:mysql://neptune:3306/dbtest");
>> properties.put("openEjbDatabase.UserName", "sa");
>> properties.put("openEjbDatabase.PassWord", "");
>>
>> context = new InitialContext(properties);
>> Object obj = context.lookup("RestaurantDao3Local");
>> dao = (IDao) obj;
>> }
>> }
>>
>> And the relevant dao code:
>> �...@resource
>> private UserTransaction utx;
>> @Override
>> public Restaurant create(Restaurant obj)
>> {
>> Restaurant created = obj;
>> try
>> {
>> utx.begin();
>> obj = getEntityManager().merge(obj);
>> getEntityManager().persist(obj);
>> getEntityManager().flush();
>> utx.commit();
>> } catch (Exception e)
>> {
>> e.printStackTrace();
>> }
>> return created;
>> }
>>
>> The exception I am getting:
>> <openjpa-1.2.1-r752877:753278 nonfatal user error>
>> org.apache.openjpa.persistence.TransactionRequiredException: Can only
>> perform operation while a transaction is active.
>> at
>> org.apache.openjpa.kernel.BrokerImpl.assertActiveTransaction(BrokerImpl.java:4380)
>> at
>> org.apache.openjpa.kernel.DelegatingBroker.assertActiveTransaction(DelegatingBroker.java:1330)
>> at
>> org.apache.openjpa.persistence.EntityManagerImpl.flush(EntityManagerImpl.java:591)
>> at
>> org.apache.openejb.persistence.JtaEntityManager.flush(JtaEntityManager.java:130)
>>
>> This is my persistence.xml:
>>
>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>> <persistence version="1.0"
>> xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
>> http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
>> http://java.sun.com/xml/ns/persistence/orm
>> http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
>> xmlns="http://java.sun.com/xml/ns/persistence"
>> xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
>> <persistence-unit name="Testing" transaction-type="RESOURCE_LOCAL">
>> <class>ws.mansour.entities.Restaurant</class>
>> </persistence-unit>
>> </persistence>
>>
>>
>> I do have few quesitons here:
>> 1- In the jndi Resource, I added openEjbDatabase as a DataSource, but
>> I don't understand how did it got picked by other DAO operations (ie.
>> read).
>> 2- I am using RESOURCE_LOCAL at transaction type, which indicates that
>> the container (context) will not handle this. How do I create a
>> tranaction ? With spring I was not able to do
>> entityManager.getTranaction(), because the entityManager injected by
>> spring is proxied (AFAIK). Doing this here, will give me another
>> error, for example:
>> try
>> {
>> getEntityManager().getTransaction().begin();
>> obj = getEntityManager().merge(obj);
>> getEntityManager().persist(obj);
>> getEntityManager().flush();
>> getEntityManager().getTransaction().commit();
>> } catch (Exception e)
>>
>> will give:
>>
>> java.lang.IllegalStateException: A JTA EntityManager can not use the
>> EntityTransaction API. See JPA 1.0 section 5.5
>> at
>> org.apache.openejb.persistence.JtaEntityManager.getTransaction(JtaEntityManager.java:220)
>>
>> What am I doing wrong ?
>>
>
>