Add support for the new JPA 2 API from July 23 2009 (only the top level package. Subpackages have not been updated. Also partially implement PersistenceUnitUtil

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17305 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Emmanuel Bernard 2009-08-14 18:29:45 +00:00
parent 5f27074c73
commit 28207a2eb1
6 changed files with 273 additions and 133 deletions

View File

@ -38,6 +38,7 @@ import javax.persistence.PersistenceContextType;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.TransactionRequiredException; import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.QueryBuilder; import javax.persistence.criteria.QueryBuilder;
import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.Metamodel;
@ -125,7 +126,28 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
public Query createQuery(CriteriaQuery criteriaQuery) { public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass) {
throw new UnsupportedOperationException( "Not yet implemented" );
}
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
// TODO-STEVE : here is the interpretation/compilation portion.
// One option is to build on top of the existing
// org.hibernate.loader.custom.CustomQuery infastructure
// (which is how native sql queries are implemented e.g.).
// If so, then here we could interpret the criteria into
// a CustomQuery instance which is passed into the
// Query instance returned here. We would then call into
// the various SessionImplementor methods for execution
// such as #listCustomQuery and #scrollCustomQuery.
//
// The drawback to this (^^) approach is that CustomQuery +
// SessionImplementor combo does not support #executeUpdate
// processing...
throw new UnsupportedOperationException( "Not yet implemented!" );
}
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery, Class<T> resultClass) {
// TODO-STEVE : here is the interpretation/compilation portion. // TODO-STEVE : here is the interpretation/compilation portion.
// One option is to build on top of the existing // One option is to build on top of the existing
// org.hibernate.loader.custom.CustomQuery infastructure // org.hibernate.loader.custom.CustomQuery infastructure
@ -160,6 +182,11 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
throw new UnsupportedOperationException( "Not yet implemented" );
}
public Query createNativeQuery(String sqlString) { public Query createNativeQuery(String sqlString) {
//adjustFlushMode(); //adjustFlushMode();
try { try {

View File

@ -23,6 +23,7 @@ package org.hibernate.ejb;
import java.util.Map; import java.util.Map;
import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.spi.PersistenceUnitTransactionType; import javax.persistence.spi.PersistenceUnitTransactionType;
import org.hibernate.Session; import org.hibernate.Session;

View File

@ -28,15 +28,19 @@ import java.io.Serializable;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceContextType;
import javax.persistence.Cache; import javax.persistence.Cache;
import javax.persistence.PersistenceUnitUtil;
import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.Metamodel;
import javax.persistence.criteria.QueryBuilder; import javax.persistence.criteria.QueryBuilder;
import javax.persistence.spi.PersistenceUnitTransactionType; import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.persistence.spi.LoadState;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.Hibernate;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.ejb.criteria.QueryBuilderImpl; import org.hibernate.ejb.criteria.QueryBuilderImpl;
import org.hibernate.ejb.metamodel.MetamodelImpl; import org.hibernate.ejb.metamodel.MetamodelImpl;
import org.hibernate.ejb.util.PersistenceUtilHelper;
/** /**
* Actual Hiberate implementation of {@link javax.persistence.EntityManagerFactory}. * Actual Hiberate implementation of {@link javax.persistence.EntityManagerFactory}.
@ -52,6 +56,7 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
private final Class sessionInterceptorClass; private final Class sessionInterceptorClass;
private final QueryBuilderImpl criteriaQueryBuilder; private final QueryBuilderImpl criteriaQueryBuilder;
private final Metamodel metamodel; private final Metamodel metamodel;
private final HibernatePersistenceUnitUtil util;
public EntityManagerFactoryImpl( public EntityManagerFactoryImpl(
SessionFactory sessionFactory, SessionFactory sessionFactory,
@ -73,6 +78,7 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
this.metamodel = null; this.metamodel = null;
} }
this.criteriaQueryBuilder = new QueryBuilderImpl( this ); this.criteriaQueryBuilder = new QueryBuilderImpl( this );
this.util = new HibernatePersistenceUnitUtil( this );
} }
public EntityManager createEntityManager() { public EntityManager createEntityManager() {
@ -114,6 +120,10 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
return new JPACache( sessionFactory ); return new JPACache( sessionFactory );
} }
public PersistenceUnitUtil getPersistenceUnitUtil() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public boolean isOpen() { public boolean isOpen() {
return ! sessionFactory.isClosed(); return ! sessionFactory.isClosed();
} }
@ -148,4 +158,35 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
// sessionFactory.getCache().evictQueryRegions(); // sessionFactory.getCache().evictQueryRegions();
} }
} }
private static class HibernatePersistenceUnitUtil implements PersistenceUnitUtil, Serializable {
private final EntityManagerFactoryImpl emf;
private HibernatePersistenceUnitUtil(EntityManagerFactoryImpl emf) {
this.emf = emf;
}
public boolean isLoaded(Object entity, String attributeName) {
LoadState state = PersistenceUtilHelper.isLoadedWithoutReference( entity, attributeName );
if (state == LoadState.LOADED) {
return true;
}
else if (state == LoadState.NOT_LOADED ) {
return false;
}
else {
return PersistenceUtilHelper.isLoadedWithReference( entity, attributeName ) != LoadState.NOT_LOADED;
}
}
public boolean isLoaded(Object entity) {
return PersistenceUtilHelper.isLoaded( entity ) != LoadState.NOT_LOADED;
}
public Object getIdentifier(Object entity) {
throw new UnsupportedOperationException( "Not yet implemented" );
}
}
} }

View File

@ -36,6 +36,7 @@ import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.LoadState; import javax.persistence.spi.LoadState;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.ejb.util.PersistenceUtilHelper;
import org.hibernate.intercept.FieldInterceptionHelper; import org.hibernate.intercept.FieldInterceptionHelper;
import org.hibernate.intercept.FieldInterceptor; import org.hibernate.intercept.FieldInterceptor;
import org.hibernate.collection.PersistentCollection; import org.hibernate.collection.PersistentCollection;
@ -170,140 +171,15 @@ public class HibernatePersistence implements javax.persistence.spi.PersistencePr
} }
public LoadState isLoadedWithoutReference(Object proxy, String property) { public LoadState isLoadedWithoutReference(Object proxy, String property) {
Object entity; return PersistenceUtilHelper.isLoadedWithoutReference( proxy, property );
boolean sureFromUs = false;
if ( proxy instanceof HibernateProxy ) {
LazyInitializer li = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
return LoadState.NOT_LOADED;
}
else {
entity = li.getImplementation();
}
sureFromUs = true;
}
else {
entity = proxy;
}
//we are instrumenting but we can't assume we are the only ones
if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
FieldInterceptor interceptor = FieldInterceptionHelper.extractFieldInterceptor( entity );
final boolean isInitialized = interceptor == null || interceptor.isInitialized( property );
LoadState state;
if (isInitialized && interceptor != null) {
//property is loaded according to bytecode enhancement, but is it loaded as far as association?
//it's ours, we can read
state = isLoaded( get( entity, property ) );
//it's ours so we know it's loaded
if (state == LoadState.UNKNOWN) state = LoadState.LOADED;
}
else if ( interceptor != null && (! isInitialized)) {
state = LoadState.NOT_LOADED;
}
else if ( sureFromUs ) { //interceptor == null
//property is loaded according to bytecode enhancement, but is it loaded as far as association?
//it's ours, we can read
state = isLoaded( get( entity, property ) );
//it's ours so we know it's loaded
if (state == LoadState.UNKNOWN) state = LoadState.LOADED;
}
else {
state = LoadState.UNKNOWN;
}
return state;
}
else {
//can't do sureFromUs ? LoadState.LOADED : LoadState.UNKNOWN;
//is that an association?
return LoadState.UNKNOWN;
}
} }
public LoadState isLoadedWithReference(Object proxy, String property) { public LoadState isLoadedWithReference(Object proxy, String property) {
//for sure we don't instrument and for sure it's not a lazy proxy return PersistenceUtilHelper.isLoadedWithReference( proxy, property );
Object object = get(proxy, property);
return isLoaded( object );
}
private Object get(Object proxy, String property) {
final Class<?> clazz = proxy.getClass();
try {
try {
final Field field = clazz.getField( property );
setAccessibility( field );
return field.get( proxy );
}
catch ( NoSuchFieldException e ) {
final Method method = getMethod( clazz, property );
if (method != null) {
setAccessibility( method );
return method.invoke( proxy );
}
else {
throw new PersistenceException( "Unable to find field or method: "
+ clazz + "#"
+ property);
}
}
}
catch ( IllegalAccessException e ) {
throw new PersistenceException( "Unable to access field or method: "
+ clazz + "#"
+ property, e);
}
catch ( InvocationTargetException e ) {
throw new PersistenceException( "Unable to access field or method: "
+ clazz + "#"
+ property, e);
}
}
/**
* Returns the method with the specified name or <code>null</code> if it does not exist.
*
* @param clazz The class to check.
* @param methodName The method name.
*
* @return Returns the method with the specified name or <code>null</code> if it does not exist.
*/
public static Method getMethod(Class<?> clazz, String methodName) {
try {
char string[] = methodName.toCharArray();
string[0] = Character.toUpperCase( string[0] );
methodName = new String( string );
try {
return clazz.getMethod( "get" + methodName );
}
catch ( NoSuchMethodException e ) {
return clazz.getMethod( "is" + methodName );
}
}
catch ( NoSuchMethodException e ) {
return null;
}
}
public static void setAccessibility(Member member) {
if ( !Modifier.isPublic( member.getModifiers() ) ) {
//Sun's ease of use, sigh...
( ( AccessibleObject ) member ).setAccessible( true );
}
} }
public LoadState isLoaded(Object o) { public LoadState isLoaded(Object o) {
if ( o instanceof HibernateProxy ) { return PersistenceUtilHelper.isLoaded(o);
final boolean isInitialized = !( ( HibernateProxy ) o ).getHibernateLazyInitializer().isUninitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
}
else if ( o instanceof PersistentCollection ) {
final boolean isInitialized = ( ( PersistentCollection ) o ).wasInitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
}
else {
return LoadState.UNKNOWN;
}
} }
/** /**

View File

@ -38,6 +38,7 @@ import javax.persistence.TemporalType;
import static javax.persistence.TemporalType.*; import static javax.persistence.TemporalType.*;
import javax.persistence.TransactionRequiredException; import javax.persistence.TransactionRequiredException;
import javax.persistence.LockModeType; import javax.persistence.LockModeType;
import javax.persistence.Parameter;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -395,13 +396,48 @@ public class QueryImpl implements Query, HibernateQuery {
} }
} }
public Map<String, Object> getNamedParameters() { //FIXME
//FIXME public Set<Parameter<?>> getParameters() {
return null; //To change body of implemented methods use File | Settings | File Templates. return null; //To change body of implemented methods use File | Settings | File Templates.
} }
public List getPositionalParameters() { //FIXME
//FIXME public Parameter<?> getParameter(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
//FIXME
public Parameter<?> getParameter(int position) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
//FIXME
public <T> Parameter<T> getParameter(String name, Class<T> type) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
//FIXME
public <T> Parameter<T> getParameter(int position, Class<T> type) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
//FIXME
public boolean isBound(Parameter<?> param) {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
//FIXME
public <T> T getParameterValue(Parameter<T> param) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
//FIXME
public Object getParameterValue(String name) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
//FIXME
public Object getParameterValue(int position) {
return null; //To change body of implemented methods use File | Settings | File Templates. return null; //To change body of implemented methods use File | Settings | File Templates.
} }

View File

@ -0,0 +1,159 @@
package org.hibernate.ejb.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.lang.reflect.AccessibleObject;
import javax.persistence.spi.LoadState;
import javax.persistence.PersistenceException;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.intercept.FieldInterceptionHelper;
import org.hibernate.intercept.FieldInterceptor;
import org.hibernate.collection.PersistentCollection;
/**
* @author Emmanuel Bernard
*/
public class PersistenceUtilHelper {
public static LoadState isLoadedWithoutReference(Object proxy, String property) {
Object entity;
boolean sureFromUs = false;
if ( proxy instanceof HibernateProxy ) {
LazyInitializer li = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
return LoadState.NOT_LOADED;
}
else {
entity = li.getImplementation();
}
sureFromUs = true;
}
else {
entity = proxy;
}
//we are instrumenting but we can't assume we are the only ones
if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
FieldInterceptor interceptor = FieldInterceptionHelper.extractFieldInterceptor( entity );
final boolean isInitialized = interceptor == null || interceptor.isInitialized( property );
LoadState state;
if (isInitialized && interceptor != null) {
//property is loaded according to bytecode enhancement, but is it loaded as far as association?
//it's ours, we can read
state = isLoaded( get( entity, property ) );
//it's ours so we know it's loaded
if (state == LoadState.UNKNOWN) state = LoadState.LOADED;
}
else if ( interceptor != null && (! isInitialized)) {
state = LoadState.NOT_LOADED;
}
else if ( sureFromUs ) { //interceptor == null
//property is loaded according to bytecode enhancement, but is it loaded as far as association?
//it's ours, we can read
state = isLoaded( get( entity, property ) );
//it's ours so we know it's loaded
if (state == LoadState.UNKNOWN) state = LoadState.LOADED;
}
else {
state = LoadState.UNKNOWN;
}
return state;
}
else {
//can't do sureFromUs ? LoadState.LOADED : LoadState.UNKNOWN;
//is that an association?
return LoadState.UNKNOWN;
}
}
public static LoadState isLoadedWithReference(Object proxy, String property) {
//for sure we don't instrument and for sure it's not a lazy proxy
Object object = get(proxy, property);
return isLoaded( object );
}
private static Object get(Object proxy, String property) {
final Class<?> clazz = proxy.getClass();
try {
try {
final Field field = clazz.getField( property );
setAccessibility( field );
return field.get( proxy );
}
catch ( NoSuchFieldException e ) {
final Method method = getMethod( clazz, property );
if (method != null) {
setAccessibility( method );
return method.invoke( proxy );
}
else {
throw new PersistenceException( "Unable to find field or method: "
+ clazz + "#"
+ property);
}
}
}
catch ( IllegalAccessException e ) {
throw new PersistenceException( "Unable to access field or method: "
+ clazz + "#"
+ property, e);
}
catch ( InvocationTargetException e ) {
throw new PersistenceException( "Unable to access field or method: "
+ clazz + "#"
+ property, e);
}
}
/**
* Returns the method with the specified name or <code>null</code> if it does not exist.
*
* @param clazz The class to check.
* @param methodName The method name.
*
* @return Returns the method with the specified name or <code>null</code> if it does not exist.
*/
private static Method getMethod(Class<?> clazz, String methodName) {
try {
char string[] = methodName.toCharArray();
string[0] = Character.toUpperCase( string[0] );
methodName = new String( string );
try {
return clazz.getMethod( "get" + methodName );
}
catch ( NoSuchMethodException e ) {
return clazz.getMethod( "is" + methodName );
}
}
catch ( NoSuchMethodException e ) {
return null;
}
}
private static void setAccessibility(Member member) {
if ( !Modifier.isPublic( member.getModifiers() ) ) {
//Sun's ease of use, sigh...
( ( AccessibleObject ) member ).setAccessible( true );
}
}
public static LoadState isLoaded(Object o) {
if ( o instanceof HibernateProxy ) {
final boolean isInitialized = !( ( HibernateProxy ) o ).getHibernateLazyInitializer().isUninitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
}
else if ( o instanceof PersistentCollection ) {
final boolean isInitialized = ( ( PersistentCollection ) o ).wasInitialized();
return isInitialized ? LoadState.LOADED : LoadState.NOT_LOADED;
}
else {
return LoadState.UNKNOWN;
}
}
}