full support for JPA 2.0 PersistenceUnitInfo SPI (for compatibility with Hibernate 3.5 beta 3; SPR-6408)
This commit is contained in:
parent
5c41e2c6e1
commit
0ba8375546
|
|
@ -29,9 +29,9 @@ import org.springframework.core.io.ResourceLoader;
|
|||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.jdbc.datasource.lookup.SingleDataSourceLookup;
|
||||
import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
|
||||
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
|
||||
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
|
||||
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
|
||||
import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -195,8 +195,8 @@ public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManage
|
|||
|
||||
this.persistenceUnitInfo = determinePersistenceUnitInfo(managerToUse);
|
||||
JpaVendorAdapter jpaVendorAdapter = getJpaVendorAdapter();
|
||||
if (jpaVendorAdapter != null && this.persistenceUnitInfo instanceof MutablePersistenceUnitInfo) {
|
||||
((MutablePersistenceUnitInfo) this.persistenceUnitInfo).setPersistenceProviderPackageName(
|
||||
if (jpaVendorAdapter != null && this.persistenceUnitInfo instanceof SmartPersistenceUnitInfo) {
|
||||
((SmartPersistenceUnitInfo) this.persistenceUnitInfo).setPersistenceProviderPackageName(
|
||||
jpaVendorAdapter.getPersistenceProviderRootPackage());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -17,12 +17,14 @@
|
|||
package org.springframework.orm.jpa.persistenceunit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.spi.PersistenceUnitInfo;
|
||||
import javax.sql.DataSource;
|
||||
|
|
@ -40,6 +42,7 @@ import org.springframework.instrument.classloading.LoadTimeWeaver;
|
|||
import org.springframework.jdbc.datasource.lookup.DataSourceLookup;
|
||||
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
|
||||
import org.springframework.jdbc.datasource.lookup.MapDataSourceLookup;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -78,7 +81,8 @@ public class DefaultPersistenceUnitManager
|
|||
public final static String ORIGINAL_DEFAULT_PERSISTENCE_UNIT_ROOT_LOCATION = "classpath:";
|
||||
|
||||
|
||||
/** Location of persistence.xml file(s) */
|
||||
private static final boolean jpa2ApiPresent = ClassUtils.hasMethod(PersistenceUnitInfo.class, "getSharedCacheMode");
|
||||
|
||||
private String[] persistenceXmlLocations = new String[] {DEFAULT_PERSISTENCE_XML_LOCATION};
|
||||
|
||||
private String defaultPersistenceUnitRootLocation = ORIGINAL_DEFAULT_PERSISTENCE_UNIT_ROOT_LOCATION;
|
||||
|
|
@ -95,8 +99,7 @@ public class DefaultPersistenceUnitManager
|
|||
|
||||
private final Set<String> persistenceUnitInfoNames = new HashSet<String>();
|
||||
|
||||
private final Map<String, MutablePersistenceUnitInfo> persistenceUnitInfos =
|
||||
new HashMap<String, MutablePersistenceUnitInfo>();
|
||||
private final Map<String, PersistenceUnitInfo> persistenceUnitInfos = new HashMap<String, PersistenceUnitInfo>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -273,8 +276,7 @@ public class DefaultPersistenceUnitManager
|
|||
this.persistenceUnitInfoNames.clear();
|
||||
this.persistenceUnitInfos.clear();
|
||||
SpringPersistenceUnitInfo[] puis = readPersistenceUnitInfos();
|
||||
for (int i = 0; i < puis.length; i++) {
|
||||
SpringPersistenceUnitInfo pui = puis[i];
|
||||
for (SpringPersistenceUnitInfo pui : puis) {
|
||||
if (pui.getPersistenceUnitRootUrl() == null) {
|
||||
pui.setPersistenceUnitRootUrl(determineDefaultPersistenceUnitRootUrl());
|
||||
}
|
||||
|
|
@ -290,7 +292,12 @@ public class DefaultPersistenceUnitManager
|
|||
postProcessPersistenceUnitInfo(pui);
|
||||
String name = pui.getPersistenceUnitName();
|
||||
this.persistenceUnitInfoNames.add(name);
|
||||
this.persistenceUnitInfos.put(name, pui);
|
||||
PersistenceUnitInfo puiToStore = pui;
|
||||
if (jpa2ApiPresent) {
|
||||
puiToStore = (PersistenceUnitInfo) Proxy.newProxyInstance(SmartPersistenceUnitInfo.class.getClassLoader(),
|
||||
new Class[] {SmartPersistenceUnitInfo.class}, new Jpa2PersistenceUnitInfoDecorator(pui));
|
||||
}
|
||||
this.persistenceUnitInfos.put(name, puiToStore);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,7 +338,7 @@ public class DefaultPersistenceUnitManager
|
|||
* @param persistenceUnitName the name of the desired persistence unit
|
||||
* @return the PersistenceUnitInfo in mutable form, or <code>null</code> if not available
|
||||
*/
|
||||
protected final MutablePersistenceUnitInfo getPersistenceUnitInfo(String persistenceUnitName) {
|
||||
protected final PersistenceUnitInfo getPersistenceUnitInfo(String persistenceUnitName) {
|
||||
return this.persistenceUnitInfos.get(persistenceUnitName);
|
||||
}
|
||||
|
||||
|
|
@ -387,4 +394,45 @@ public class DefaultPersistenceUnitManager
|
|||
return pui;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decorator that exposes a JPA 2.0 compliant PersistenceUnitInfo interface for a
|
||||
* JPA 1.0 based SpringPersistenceUnitInfo object, adapting the <code>getSharedCacheMode</code>
|
||||
* and <code>getValidationMode</code> methods from String names to enum return values.
|
||||
*/
|
||||
private static class Jpa2PersistenceUnitInfoDecorator implements InvocationHandler {
|
||||
|
||||
private final SpringPersistenceUnitInfo target;
|
||||
|
||||
private final Class<? extends Enum> sharedCacheModeEnum;
|
||||
|
||||
private final Class<? extends Enum> validationModeEnum;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Jpa2PersistenceUnitInfoDecorator(SpringPersistenceUnitInfo target) {
|
||||
this.target = target;
|
||||
try {
|
||||
this.sharedCacheModeEnum = (Class<? extends Enum>)
|
||||
ClassUtils.forName("javax.persistence.SharedCacheMode", PersistenceUnitInfo.class.getClassLoader());
|
||||
this.validationModeEnum = (Class<? extends Enum>)
|
||||
ClassUtils.forName("javax.persistence.ValidationMode", PersistenceUnitInfo.class.getClassLoader());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("JPA 2.0 API enum types not present", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getName().equals("getSharedCacheMode")) {
|
||||
return Enum.valueOf(this.sharedCacheModeEnum, this.target.getSharedCacheModeName());
|
||||
}
|
||||
else if (method.getName().equals("getValidationMode")) {
|
||||
return Enum.valueOf(this.validationModeEnum, this.target.getValidationModeName());
|
||||
}
|
||||
else {
|
||||
return method.invoke(this.target, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -20,9 +20,7 @@ import java.net.URL;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.spi.ClassTransformer;
|
||||
import javax.persistence.spi.PersistenceUnitInfo;
|
||||
import javax.persistence.spi.PersistenceUnitTransactionType;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
|
@ -41,7 +39,7 @@ import org.springframework.util.ClassUtils;
|
|||
* @author Costin Leau
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MutablePersistenceUnitInfo implements PersistenceUnitInfo {
|
||||
public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
|
||||
|
||||
private String persistenceUnitName;
|
||||
|
||||
|
|
@ -65,6 +63,8 @@ public class MutablePersistenceUnitInfo implements PersistenceUnitInfo {
|
|||
|
||||
private Properties properties = new Properties();
|
||||
|
||||
private String persistenceXMLSchemaVersion = "1.0";
|
||||
|
||||
private String persistenceProviderPackageName;
|
||||
|
||||
|
||||
|
|
@ -169,6 +169,14 @@ public class MutablePersistenceUnitInfo implements PersistenceUnitInfo {
|
|||
return this.properties;
|
||||
}
|
||||
|
||||
public void setPersistenceXMLSchemaVersion(String persistenceXMLSchemaVersion) {
|
||||
this.persistenceXMLSchemaVersion = persistenceXMLSchemaVersion;
|
||||
}
|
||||
|
||||
public String getPersistenceXMLSchemaVersion() {
|
||||
return this.persistenceXMLSchemaVersion;
|
||||
}
|
||||
|
||||
public void setPersistenceProviderPackageName(String persistenceProviderPackageName) {
|
||||
this.persistenceProviderPackageName = persistenceProviderPackageName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -52,6 +52,10 @@ import org.springframework.util.xml.SimpleSaxErrorHandler;
|
|||
*/
|
||||
class PersistenceUnitReader {
|
||||
|
||||
private static final String PERSISTENCE_UNIT = "persistence-unit";
|
||||
|
||||
private static final String UNIT_NAME = "name";
|
||||
|
||||
private static final String MAPPING_FILE_NAME = "mapping-file";
|
||||
|
||||
private static final String JAR_FILE_URL = "jar-file";
|
||||
|
|
@ -62,17 +66,17 @@ class PersistenceUnitReader {
|
|||
|
||||
private static final String PROVIDER = "provider";
|
||||
|
||||
private static final String EXCLUDE_UNLISTED_CLASSES = "exclude-unlisted-classes";
|
||||
private static final String TRANSACTION_TYPE = "transaction-type";
|
||||
|
||||
private static final String NON_JTA_DATA_SOURCE = "non-jta-data-source";
|
||||
private static final String SHARED_CACHE_MODE = "shared-cache-mode";
|
||||
|
||||
private static final String VALIDATION_MODE = "validation-mode";
|
||||
|
||||
private static final String JTA_DATA_SOURCE = "jta-data-source";
|
||||
|
||||
private static final String TRANSACTION_TYPE = "transaction-type";
|
||||
private static final String NON_JTA_DATA_SOURCE = "non-jta-data-source";
|
||||
|
||||
private static final String PERSISTENCE_UNIT = "persistence-unit";
|
||||
|
||||
private static final String UNIT_NAME = "name";
|
||||
private static final String EXCLUDE_UNLISTED_CLASSES = "exclude-unlisted-classes";
|
||||
|
||||
private static final String META_INF = "META-INF";
|
||||
|
||||
|
|
@ -274,6 +278,18 @@ class PersistenceUnitReader {
|
|||
unitInfo.setTransactionType(PersistenceUnitTransactionType.valueOf(txType));
|
||||
}
|
||||
|
||||
// set JPA 2.0 shared cache mode
|
||||
String cacheMode = persistenceUnit.getAttribute(SHARED_CACHE_MODE).trim();
|
||||
if (StringUtils.hasText(cacheMode)) {
|
||||
unitInfo.setSharedCacheModeName(cacheMode);
|
||||
}
|
||||
|
||||
// set JPA 2.0 validation mode
|
||||
String validationMode = persistenceUnit.getAttribute(VALIDATION_MODE).trim();
|
||||
if (StringUtils.hasText(validationMode)) {
|
||||
unitInfo.setValidationModeName(validationMode);
|
||||
}
|
||||
|
||||
// data-source
|
||||
String jtaDataSource = DomUtils.getChildElementValueByTagName(persistenceUnit, JTA_DATA_SOURCE);
|
||||
if (StringUtils.hasText(jtaDataSource)) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa.persistenceunit;
|
||||
|
||||
import javax.persistence.spi.PersistenceUnitInfo;
|
||||
|
||||
/**
|
||||
* Extension of the standard JPA PersistenceUnitInfo interface, for advanced collaboration
|
||||
* between Spring's {@link org.springframework.orm.jpa.LocalEntityManagerFactoryBean} and
|
||||
* {@link PersistenceUnitManager} implementations.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.1
|
||||
* @see PersistenceUnitManager
|
||||
* @see org.springframework.orm.jpa.LocalEntityManagerFactoryBean
|
||||
*/
|
||||
public interface SmartPersistenceUnitInfo extends PersistenceUnitInfo {
|
||||
|
||||
/**
|
||||
* Set the persistence provider's own package name, for exclusion from class transformation.
|
||||
* @see #addTransformer(javax.persistence.spi.ClassTransformer)
|
||||
* @see #getNewTempClassLoader()
|
||||
*/
|
||||
void setPersistenceProviderPackageName(String persistenceProviderPackageName);
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -22,6 +22,7 @@ import org.springframework.core.DecoratingClassLoader;
|
|||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.instrument.classloading.SimpleThrowawayClassLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Subclass of {@link MutablePersistenceUnitInfo} that adds instrumentation hooks based on
|
||||
|
|
@ -37,11 +38,39 @@ import org.springframework.util.Assert;
|
|||
*/
|
||||
class SpringPersistenceUnitInfo extends MutablePersistenceUnitInfo {
|
||||
|
||||
private static final String DEFAULT_SHARED_CACHE_MODE_NAME = "UNSPECIFIED";
|
||||
|
||||
private static final String DEFAULT_VALIDATION_MODE_NAME = "AUTO";
|
||||
|
||||
|
||||
private String sharedCacheModeName = DEFAULT_SHARED_CACHE_MODE_NAME;
|
||||
|
||||
private String validationModeName = DEFAULT_VALIDATION_MODE_NAME;
|
||||
|
||||
private LoadTimeWeaver loadTimeWeaver;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
|
||||
public void setSharedCacheModeName(String sharedCacheModeName) {
|
||||
this.sharedCacheModeName =
|
||||
(StringUtils.hasLength(sharedCacheModeName) ? sharedCacheModeName : DEFAULT_SHARED_CACHE_MODE_NAME);
|
||||
}
|
||||
|
||||
public String getSharedCacheModeName() {
|
||||
return this.sharedCacheModeName;
|
||||
}
|
||||
|
||||
public void setValidationModeName(String validationModeName) {
|
||||
this.validationModeName =
|
||||
(StringUtils.hasLength(validationModeName) ? validationModeName : DEFAULT_VALIDATION_MODE_NAME);
|
||||
}
|
||||
|
||||
public String getValidationModeName() {
|
||||
return this.validationModeName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize this PersistenceUnitInfo with the LoadTimeWeaver SPI interface
|
||||
* used by Spring to add instrumentation to the current class loader.
|
||||
|
|
|
|||
Loading…
Reference in New Issue