OPENJPA-1803: Add support for obtaining a connection via EntityManager.unwrap. Patch contributed by Sebastian Laskawiec.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1138059 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Richard G. Curtis 2011-06-21 15:46:46 +00:00
parent cd486f73f5
commit 053d81db95
3 changed files with 37 additions and 15 deletions

View File

@ -45,7 +45,7 @@ public class TestUnwrap extends SingleEMFTestCase {
org.apache.openjpa.kernel.Query.class,
org.apache.openjpa.kernel.QueryImpl.class
};
for (Class c : validCasts) {
for (Class<?> c : validCasts) {
Object unwrapped = query.unwrap(c);
assertTrue(c.isInstance(unwrapped));
}
@ -72,6 +72,24 @@ public class TestUnwrap extends SingleEMFTestCase {
em.close();
}
/**
* Tests a EntityManager can be unwrapped as an instance of a series of
* class or interface.
*/
public void testValidOtherUnwrap() {
EntityManager em = emf.createEntityManager();
Class<?>[] validCasts = new Class[] {
java.sql.Connection.class
};
for (Class<?> c : validCasts) {
Object unwrapped = em.unwrap(c);
assertTrue(c.isInstance(unwrapped));
}
em.close();
}
/**
* Tests a EntityManager can not be unwrapped as Object class, null or an interface.
* And each such failure raises a Persistence Exception and causes an active transaction

View File

@ -30,6 +30,7 @@ import java.io.ObjectStreamClass;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
@ -1660,11 +1661,16 @@ public class EntityManagerImpl
* that is not wrapped by this receiver.
*/
public <T> T unwrap(Class<T> cls) {
Object[] delegates = new Object[]{_broker.getInnermostDelegate(),
_broker.getDelegate(), _broker, this};
for (Object o : delegates) {
if (cls != null && cls != Object.class && cls.isInstance(o))
return (T)o;
if (cls != null && cls != Object.class) {
Object[] delegates = new Object[] { _broker.getInnermostDelegate(), _broker.getDelegate(), _broker, this };
for (Object o : delegates) {
if (cls.isInstance(o))
return (T) o;
}
// Only call getConnection() once we are certain that is the type that we need to unwrap.
if (cls.isAssignableFrom(Connection.class)) {
return (T) getConnection();
}
}
// Set this transaction to rollback only (as per spec) here because the raised exception
// does not go through normal exception translation pathways

View File

@ -599,14 +599,11 @@ about the database in use (e.g. version, JDBC driver version).
</indexterm>
<para>
The JPA standard defines how to access JDBC connections from enterprise beans.
OpenJPA also provides APIs to access an <classname>EntityManager</classname>'s
connection, or to retrieve a connection directly from the <classname>
OpenJPA also provides APIs to retrieve a connection directly from the <classname>
EntityManagerFactory</classname>'s <classname>DataSource</classname>.
</para>
<para>
The
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityManager.html">
<methodname>OpenJPAEntityManager.getConnection</methodname></ulink> method
The <methodname>EntityManager.unwrap(java.sql.Connection.class)</methodname> method
returns an <classname>EntityManager</classname>'s connection. If the <classname>
EntityManager</classname> does not already have a connection, it will obtain
one. The returned connection is only guaranteed to be transactionally consistent
@ -624,13 +621,14 @@ connection is not released if a datastore transaction is in progress.
Using the EntityManager's Connection
</title>
<programlisting>
import java.sql.*;
import org.apache.openjpa.persistence.*;
import java.sql.Connection;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
...
OpenJPAEntityManager kem = OpenJPAPersistence.cast(em);
Connection conn = (Connection) kem.getConnection();
EntityManager em = emf.createEntityManager();
Connection conn = (Connection) em.unwrap(java.sql.Connection.class);
// do JDBC stuff