Dynamic Persistence Units in EJB3

| | Comments (1)

I gotta say, again, that I really think JPA is great. It took almost a decade, but Sun got pretty much everything right. I love just putting annotations everywhere, and anyone who thinks that is a bad idea is a dodo-head. Die XML, die!

Unfortunately, the legacy of deployment descriptors still lives on in the dusty corners of the EJB3 spec. One thing that you still can't do without a deployment descriptor is define a new Persistence Unit.

That's a fairly big omission. In the case of the app I am writing, a big part of what I need to do is allow the user to configure new databases and connect to them. I don't know what those databases are until runtime, and if I happen to want to talk to those databases via JPA, I'm pretty much out of luck - at least as far as the spec is concerned.

Here is a vendor specific-solution for Hibernate. It actually took a while for me to google this together, so maybe this will save someone some time. Maybe my googling skillz are not as mad as they used to be. Anyway.


  import org.hibernate.ejb.Ejb3Configuration;
  import java.sql.DataSource;
  import java.util.Properties;

// ...

  @SuppressWarnings("deprecation")
  public static EntityManagerFactory 
    createEMF(DataSource ds,
              Class[] entityClasses,
              Properties props)
  {
    Ejb3Configuration ejb3conf = 
      new Ejb3Configuration();
    ejb3conf.setDataSource(ds);
    //
    // set any fixed properties you want
    ejb3conf.setProperty("hibernate.dialect",  
             org.hibernate.dialect.HSQLDialect); 
    ejb3conf.setProperty("hibernate.show_sql", 
             "false");
    ejb3conf.setProperty("hibernate.hbm2ddl.auto", 
             "update");

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

1 Comments

Andrew Geweke said:

I had much the same feelings when I started using JPA several months ago -- hallelujah! I feel like EJB2 was so insanely complex that I couldn't possibly imagine them fixing *all* of it with EJB3, but, honestly, they really did. There are a few little weird things here and there, but, all in all, it feels very, very good and infinitely lighter-weight than EJB3.

Better yet, I was able to use the full JPA stack in a program I wrote that used no other pieces of EJB -- and I didn't write a single line of XML. Very nice.

(I am now doing Rails work, and I have to admit that, in the end, I prefer it...but the gap is unbelievably smaller than it used to be. It's about as small as it can get in a statically-typed language like Java, I suspect.)

There are still a few weird things -- I started out letting Hibernate generate my entire database schema directly from the annotated classes, which was very cool, but I had to eventually quit that because it just didn't give me fine enough control over a number of things. But, all in all, I am very, very impressed.

Leave a comment

About

My name is Patrick Calahan.

I live in San Francisco.

I do product development and consulting on Java and Business Intelligence.

This is my blog.

Contact

About this Entry

This page contains a single entry by published on April 19, 2007 11:12 AM.

Pitchwire is Live was the previous entry in this blog.

No, Let's Play Global Thermonuclear War is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by Movable Type 4.01