KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > jpa > LocalContainerEntityManagerFactoryBean


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.orm.jpa;
18
19 import javax.persistence.EntityManagerFactory;
20 import javax.persistence.PersistenceException;
21 import javax.persistence.spi.PersistenceProvider;
22 import javax.persistence.spi.PersistenceUnitInfo;
23 import javax.sql.DataSource JavaDoc;
24
25 import org.springframework.beans.BeanUtils;
26 import org.springframework.beans.factory.BeanClassLoaderAware;
27 import org.springframework.context.ResourceLoaderAware;
28 import org.springframework.core.io.ResourceLoader;
29 import org.springframework.instrument.classloading.LoadTimeWeaver;
30 import org.springframework.jdbc.datasource.lookup.SingleDataSourceLookup;
31 import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
32 import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
33 import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
34 import org.springframework.util.ClassUtils;
35
36 /**
37  * {@link org.springframework.beans.factory.FactoryBean} that creates a JPA
38  * {@link javax.persistence.EntityManagerFactory} according to JPA's standard
39  * <i>container</i> bootstrap contract. This is the most powerful way to set
40  * up a shared JPA EntityManagerFactory in a Spring application context;
41  * the EntityManagerFactory can then be passed to JPA-based DAOs via
42  * dependency injection. Note that switching to a JNDI lookup or to a
43  * {@link org.springframework.orm.jpa.LocalEntityManagerFactoryBean}
44  * definition is just a matter of configuration!
45  *
46  * <p>As with {@link LocalEntityManagerFactoryBean}, configuration settings
47  * are usually read in from a <code>META-INF/persistence.xml</code> config file,
48  * residing in the class path, according to the general JPA configuration contract.
49  * However, this FactoryBean is more flexible in that you can override the location
50  * of the <code>persistence.xml</code> file, specify the JDBC DataSources to link to,
51  * etc. Furthermore, it allows for pluggable class instrumentation through Spring's
52  * {@link org.springframework.instrument.classloading.LoadTimeWeaver} abstraction,
53  * instead of being tied to a special VM agent specified on JVM startup.
54  *
55  * <p>Internally, this FactoryBean parses the <code>persistence.xml</code> file
56  * itself and creates a corresponding {@link javax.persistence.spi.PersistenceUnitInfo}
57  * object (with further configuration merged in, such as JDBC DataSources and the
58  * Spring LoadTimeWeaver), to be passed to the chosen JPA
59  * {@link javax.persistence.spi.PersistenceProvider}. This corresponds to a
60  * local JPA container with full support for the standard JPA container contract.
61  *
62  * <p>The exposed EntityManagerFactory object will implement all the interfaces of
63  * the underlying native EntityManagerFactory returned by the PersistenceProvider,
64  * plus the {@link EntityManagerFactoryInfo} interface which exposes additional
65  * metadata as assembled by this FactoryBean.
66  *
67  * @author Juergen Hoeller
68  * @author Rod Johnson
69  * @since 2.0
70  * @see #setPersistenceXmlLocation
71  * @see #setJpaProperties
72  * @see #setJpaVendorAdapter
73  * @see #setLoadTimeWeaver
74  * @see #setDataSource
75  * @see EntityManagerFactoryInfo
76  * @see LocalEntityManagerFactoryBean
77  * @see org.springframework.orm.jpa.support.SharedEntityManagerBean
78  * @see javax.persistence.spi.PersistenceProvider#createContainerEntityManagerFactory
79  */

80 public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManagerFactoryBean
81         implements ResourceLoaderAware, BeanClassLoaderAware {
82
83     private PersistenceUnitManager persistenceUnitManager;
84
85     private final DefaultPersistenceUnitManager internalPersistenceUnitManager =
86             new DefaultPersistenceUnitManager();
87
88     private ClassLoader JavaDoc beanClassLoader = ClassUtils.getDefaultClassLoader();
89
90     private PersistenceUnitInfo persistenceUnitInfo;
91
92
93     /**
94      * Set the PersistenceUnitManager to use for obtaining the JPA persistence unit
95      * that this FactoryBean is supposed to build an EntityManagerFactory for.
96      * <p>The default is to rely on the local settings specified on this FactoryBean,
97      * such as "persistenceXmlLocation", "dataSource" and "loadTimeWeaver".
98      * <p>For reuse of existing persistence unit configuration or more advanced forms
99      * of custom persistence unit handling, consider defining a separate
100      * PersistenceUnitManager bean (typically a DefaultPersistenceUnitManager instance)
101      * and linking it in here. <code>persistence.xml</code> location, DataSource
102      * configuration and LoadTimeWeaver will be defined on that separate
103      * DefaultPersistenceUnitManager bean in such a scenario.
104      * @see #setPersistenceXmlLocation
105      * @see #setDataSource
106      * @see #setLoadTimeWeaver
107      * @see org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager
108      */

109     public void setPersistenceUnitManager(PersistenceUnitManager persistenceUnitManager) {
110         this.persistenceUnitManager = persistenceUnitManager;
111     }
112
113     /**
114      * Set the location of the <code>persistence.xml</code> file
115      * we want to use. This is a Spring resource location.
116      * <p>Default is "classpath:META-INF/persistence.xml".
117      * <p><b>NOTE: Only applied if no external PersistenceUnitManager specified.</b>
118      * @param persistenceXmlLocation a Spring resource String
119      * identifying the location of the <code>persistence.xml</code> file
120      * that this LocalContainerEntityManagerFactoryBean should parse
121      * @see #setPersistenceUnitManager
122      */

123     public void setPersistenceXmlLocation(String JavaDoc persistenceXmlLocation) {
124         this.internalPersistenceUnitManager.setPersistenceXmlLocations(new String JavaDoc[] {persistenceXmlLocation});
125     }
126
127     /**
128      * Specify the JDBC DataSource that the JPA persistence provider is supposed
129      * to use for accessing the database. This is an alternative to keeping the
130      * JDBC configuration in <code>persistence.xml</code>, passing in a Spring-managed
131      * DataSource instead.
132      * <p>In JPA speak, a DataSource passed in here will be used as "nonJtaDataSource"
133      * on the PersistenceUnitInfo passed to the PersistenceProvider, overriding
134      * data source configuration in <code>persistence.xml</code> (if any).
135      * <p><b>NOTE: Only applied if no external PersistenceUnitManager specified.</b>
136      * @see javax.persistence.spi.PersistenceUnitInfo#getNonJtaDataSource()
137      * @see #setPersistenceUnitManager
138      */

139     public void setDataSource(DataSource JavaDoc dataSource) {
140         this.internalPersistenceUnitManager.setDataSourceLookup(new SingleDataSourceLookup(dataSource));
141         this.internalPersistenceUnitManager.setDefaultDataSource(dataSource);
142     }
143
144     /**
145      * Specify the Spring LoadTimeWeaver to use for class instrumentation according
146      * to the JPA class transformer contract.
147      * <p>It is a not required to specify a LoadTimeWeaver: Most providers will be
148      * able to provide a subset of their functionality without class instrumentation
149      * as well, or operate with their VM agent specified on JVM startup.
150      * <p>In terms of Spring-provided weaving options, the most important ones are
151      * InstrumentationLoadTimeWeaver, which requires a Spring-specific (but very general)
152      * VM agent specified on JVM startup, and ReflectiveLoadTimeWeaver, which interacts
153      * with an underlying ClassLoader based on specific extended methods being available
154      * on it (for example, interacting with Spring's TomcatInstrumentableClassLoader).
155      * <p><b>NOTE: Only applied if no external PersistenceUnitManager specified.</b>
156      * @see org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver
157      * @see org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver
158      * @see org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader
159      * @see #setPersistenceUnitManager
160      */

161     public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
162         this.internalPersistenceUnitManager.setLoadTimeWeaver(loadTimeWeaver);
163     }
164     /**
165      * Set the PersistenceUnitPostProcessors to be applied to the
166      * PersistenceUnitInfo used for creating this EntityManagerFactory.
167      * <p>Such post-processors can, for example, register further entity
168      * classes and jar files, in addition to the metadata read in from
169      * <code>persistence.xml</code>.
170      * <p><b>NOTE: Only applied if no external PersistenceUnitManager specified.</b>
171      * @see #setPersistenceUnitManager
172      */

173     public void setPersistenceUnitPostProcessors(PersistenceUnitPostProcessor[] postProcessors) {
174         this.internalPersistenceUnitManager.setPersistenceUnitPostProcessors(postProcessors);
175     }
176
177
178     public void setResourceLoader(ResourceLoader resourceLoader) {
179         this.internalPersistenceUnitManager.setResourceLoader(resourceLoader);
180     }
181
182     public void setBeanClassLoader(ClassLoader JavaDoc beanClassLoader) {
183         this.beanClassLoader = beanClassLoader;
184     }
185
186
187     @Override JavaDoc
188     protected EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException {
189         PersistenceUnitManager managerToUse = this.persistenceUnitManager;
190         if (this.persistenceUnitManager == null) {
191             this.internalPersistenceUnitManager.afterPropertiesSet();
192             managerToUse = this.internalPersistenceUnitManager;
193         }
194
195         this.persistenceUnitInfo = determinePersistenceUnitInfo(managerToUse);
196
197         PersistenceProvider provider = getPersistenceProvider();
198         if (provider == null) {
199             String JavaDoc providerClassName = this.persistenceUnitInfo.getPersistenceProviderClassName();
200             if (providerClassName == null) {
201                 throw new IllegalArgumentException JavaDoc(
202                         "No PersistenceProvider specified in EntityManagerFactory configuration, " +
203                         "and chosen PersistenceUnitInfo does not specify a provider class name either");
204             }
205             Class JavaDoc providerClass = ClassUtils.resolveClassName(providerClassName, this.beanClassLoader);
206             provider = (PersistenceProvider) BeanUtils.instantiateClass(providerClass);
207         }
208         if (provider == null) {
209             throw new IllegalStateException JavaDoc("Unable to determine persistence provider. " +
210                     "Please check configuration of " + getClass().getName() + "; " +
211                     "ideally specify the appropriate JpaVendorAdapter class for this provider.");
212         }
213
214         this.nativeEntityManagerFactory =
215                 provider.createContainerEntityManagerFactory(this.persistenceUnitInfo, getJpaPropertyMap());
216         postProcessEntityManagerFactory(this.nativeEntityManagerFactory, this.persistenceUnitInfo);
217
218         return this.nativeEntityManagerFactory;
219     }
220
221
222     /**
223      * Determine the PersistenceUnitInfo to use for the EntityManagerFactory
224      * created by this bean.
225      * <p>The default implementation reads in all persistence unit infos from
226      * <code>persistence.xml</code>, as defined in the JPA specification.
227      * If no entity manager name was specified, it takes the first info in the
228      * array as returned by the reader. Otherwise, it checks for a matching name.
229      * @param persistenceUnitManager the PersistenceUnitManager to obtain from
230      * @return the chosen PersistenceUnitInfo
231      */

232     protected PersistenceUnitInfo determinePersistenceUnitInfo(PersistenceUnitManager persistenceUnitManager) {
233         if (getPersistenceUnitName() != null) {
234             return persistenceUnitManager.obtainPersistenceUnitInfo(getPersistenceUnitName());
235         }
236         else {
237             return persistenceUnitManager.obtainDefaultPersistenceUnitInfo();
238         }
239     }
240
241     /**
242      * Hook method allowing subclasses to customize the EntityManagerFactory
243      * after its creation via the PersistenceProvider.
244      * <p>The default implementation is empty.
245      * @param emf the newly created EntityManagerFactory we are working with
246      * @param pui the PersistenceUnitInfo used to configure the EntityManagerFactory
247      * @see javax.persistence.spi.PersistenceProvider#createContainerEntityManagerFactory
248      */

249     protected void postProcessEntityManagerFactory(EntityManagerFactory emf, PersistenceUnitInfo pui) {
250     }
251
252
253     public PersistenceUnitInfo getPersistenceUnitInfo() {
254         return this.persistenceUnitInfo;
255     }
256
257     public String JavaDoc getPersistenceUnitName() {
258         if (this.persistenceUnitInfo != null) {
259             return this.persistenceUnitInfo.getPersistenceUnitName();
260         }
261         return super.getPersistenceUnitName();
262     }
263
264     public DataSource JavaDoc getDataSource() {
265         if (this.persistenceUnitInfo != null) {
266             return this.persistenceUnitInfo.getNonJtaDataSource();
267         }
268         return this.internalPersistenceUnitManager.getDefaultDataSource();
269     }
270
271 }
272
Popular Tags