-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Dynamic Entity Managers and ORM
PostPosted: Thu Aug 02, 2007 12:45 pm 
Newbie

Joined: Thu Aug 02, 2007 12:30 pm
Posts: 4
Hi all,

I'm creating dynamically the entity managers I have to use with my EJB3 session beans. Doing this because I have no clue on the database schema to use until runtime. Here is the code I'm using (found this on a site, works pretty good):


private EntityManagerFactory createEMF (DataSource ds, Class[] entityClasses, Properties props) {
Ejb3Configuration ejb3conf = new Ejb3Configuration ();
ejb3conf.setDataSource (ds);

ejb3conf.setProperty ("hibernate.dialect", "org.hibernate.dialect.OracleDialect");
ejb3conf.setProperty ("hibernate.show_sql", "true");

if (props != null) {
Set<Entry<Object, Object>> entries = props.entrySet ();
for (Entry e: entries) {
ejb3conf.setProperty (e.getKey ().toString (), e.getValue ().toString ());
}
}
for (int k = 0; k < entityClasses.length; k++) {
assert entityClasses[k] != null;
ejb3conf.addAnnotatedClass (entityClasses[k]);
}
return ejb3conf.createEntityManagerFactory ();
}


Now I can perform entity operations on my database dynamically. Using this, I can get rid of persistence.xml file. The thing is, that I have to store some ORM data in my Entity Manager. If I used a persistence.xml file, this would look like this:


<persistence-unit name="SubscriptionsPU" transaction-type="JTA">

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<jta-data-source>jdbc/subs-ds</jta-data-source>

<mapping-file>subscriptions/orm.xml</mapping-file>

<properties>
<property name="oracle.orm.throw.exceptions" value="true"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
</properties>

</persistence-unit>


Anybody has a clue how I can retreive the mapping file (orm.xml) in my EntityManagerFactory object ?

thanx a lot !

hibernate version: hibernate-3.2
Name and version of the database you are using: Oracle 10g


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 02, 2007 3:03 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
ejb3Conf.addResource() is one way

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 03, 2007 6:22 am 
Newbie

Joined: Thu Aug 02, 2007 12:30 pm
Posts: 4
Thank you Emmanuel,
this is working, now I can get some named queries executed with my Entity Manager (even though some native queries did not work, but well, this is not the point for now).

Now I'm facing another problem, when I want to update the database. Seems like the container transaction around the EJB invocation is not used by my Entity Manager, I get this error:

javax.persistence.TransactionRequiredException: no transaction is in progress at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:294)


I tried several things:
- the method invocation through a container managed trasaction (using the @TransactionAttribute (TransactionAttributeType.REQUIRES_NEW) annotation). Not working.
- manually perform the transaction using these APIs:
EntityTransaction trans = entityManager.getTransaction ();
trans.begin ();
trans.commit ();
Working but not suitable.
- Calling the entityManager.joinTransaction () method before the database update query. Still not working (thought this one would work :()

any help please ?

Thanx.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 03, 2007 11:32 am 
Newbie

Joined: Thu Aug 02, 2007 12:30 pm
Posts: 4
ok I made the joinTransaction() method working by adding some properties to my entity manager factory:
- specifying the type of transaction as JTA
- specifying the hibernate lookup class of my application server Transaction Manager (Sun AS)

I used the post http://forum.hibernate.org/viewtopic.php?t=968616

I added these (using glassifsh Sun AS):

Code:
    private Properties setEMProperties () {
        Properties preparedProperties = new Properties ();
        preparedProperties.setProperty (HibernatePersistence.TRANSACTION_TYPE,
                PersistenceUnitTransactionType.JTA.name ());
        preparedProperties.setProperty ("hibernate.transaction.manager_lookup_class",
                "org.hibernate.transaction.SunONETransactionManagerLookup");
        return preparedProperties;
    }


now the transactional context works properly, will continue to perform tests.

Thanx again.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 03, 2007 2:20 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
yes that was the problem

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 10, 2007 12:05 pm 
Newbie

Joined: Thu Aug 02, 2007 12:30 pm
Posts: 4
Hi,

I've continued a bit with my "JTA Application managed entity manager" and faced another problem. It seams that the using of the joinTransaction() api has a memory leak.

Let me explain...

I've wrote an interceptor around stateless session bean methods that injects an EntityManager dynamically. If the EntityManager already exists in the retreived session instance (from the AS pool), I don't create the EntityManager, the only thing I do is calling the joinTransaction() method to associate the bean current transaction with the current EntityManager.
The thing is that this method is called each time a session bean method is called (the way it should be using an interceptor, right ?), but my test suite gets slower and slower the more the joinTransaction() method is performed.

here is the interceptor code:

Code:
    @AroundInvoke
    public Object entityManagerSelectionInterceptor (InvocationContext invocationCtx)
            throws Exception {
        if (entityManager == null) {
            // try to get the EM from the cache
            String userLogin = this.getClass ().getName ();
            if ((entityManager = this.entityManagers.get (userLogin)) == null) {
                // this code is performed only once
                // since the bean instance is alive in the pool
                entityManager = buildEntityManager (userLogin);
                // put in cache
                entityManagers.put (userLogin, entityManager);
            }
        }
        // performed each time a session bean method is called
        entityManager.joinTransaction ();
        return invocationCtx.proceed ();
    }



here are the benches:

test suite: 73,289 seconds
test suite: 79,913 seconds
test suite: 95,564 seconds
test suite: 116,339 seconds
test suite: 122,618 seconds
test suite: 126,991 seconds
test suite: 141,097 seconds

Is it possible that the EntityManager keeps ALL the transaction objects it is attached to and never releases them ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 15, 2007 9:41 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
You should not share EntityManagers, EM are cheap resources to create. I don't know exactly what is happening, possibly the EJB 3 container map of em - transaction is growing because the key cannot be reieased, it's app server dependent.
Anyway such a contract is not supported. Create another EM each time.

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.