1 /* 2 * Copyright 2002-2011 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 java.util.HashMap; 20 import java.util.Map; 21 import java.util.Properties; 22 import javax.persistence.EntityManager; 23 import javax.persistence.EntityManagerFactory; 24 25 import org.apache.commons.logging.Log; 26 import org.apache.commons.logging.LogFactory; 27 28 import org.springframework.beans.BeansException; 29 import org.springframework.beans.factory.BeanFactory; 30 import org.springframework.beans.factory.BeanFactoryAware; 31 import org.springframework.beans.factory.ListableBeanFactory; 32 import org.springframework.util.Assert; 33 import org.springframework.util.CollectionUtils; 34 35 /** 36 * Base class for any class that needs to access an EntityManagerFactory, 37 * usually in order to obtain an EntityManager. Defines common properties. 38 * 39 * <p>Not intended to be used directly. See {@link JpaAccessor}. 40 * 41 * @author Juergen Hoeller 42 * @since 2.0 43 * @see JpaAccessor 44 * @see EntityManagerFactoryUtils 45 */ 46 public abstract class EntityManagerFactoryAccessor implements BeanFactoryAware { 47 48 /** Logger available to subclasses */ 49 protected final Log logger = LogFactory.getLog(getClass()); 50 51 private EntityManagerFactory entityManagerFactory; 52 53 private String persistenceUnitName; 54 55 private final Map<String, Object> jpaPropertyMap = new HashMap<String, Object>(); 56 57 58 /** 59 * Set the JPA EntityManagerFactory that should be used to create 60 * EntityManagers. 61 * @see javax.persistence.EntityManagerFactory#createEntityManager() 62 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 63 */ setEntityManagerFactory(EntityManagerFactory emf)64 public void setEntityManagerFactory(EntityManagerFactory emf) { 65 this.entityManagerFactory = emf; 66 } 67 68 /** 69 * Return the JPA EntityManagerFactory that should be used to create 70 * EntityManagers. 71 */ getEntityManagerFactory()72 public EntityManagerFactory getEntityManagerFactory() { 73 return this.entityManagerFactory; 74 } 75 76 /** 77 * Set the name of the persistence unit to access the EntityManagerFactory for. 78 * <p>This is an alternative to specifying the EntityManagerFactory by direct reference, 79 * resolving it by its persistence unit name instead. If no EntityManagerFactory and 80 * no persistence unit name have been specified, a default EntityManagerFactory will 81 * be retrieved through finding a single unique bean of type EntityManagerFactory. 82 * @see #setEntityManagerFactory 83 */ setPersistenceUnitName(String persistenceUnitName)84 public void setPersistenceUnitName(String persistenceUnitName) { 85 this.persistenceUnitName = persistenceUnitName; 86 } 87 88 /** 89 * Return the name of the persistence unit to access the EntityManagerFactory for, if any. 90 */ getPersistenceUnitName()91 public String getPersistenceUnitName() { 92 return this.persistenceUnitName; 93 } 94 95 /** 96 * Specify JPA properties, to be passed into 97 * <code>EntityManagerFactory.createEntityManager(Map)</code> (if any). 98 * <p>Can be populated with a String "value" (parsed via PropertiesEditor) 99 * or a "props" element in XML bean definitions. 100 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 101 */ setJpaProperties(Properties jpaProperties)102 public void setJpaProperties(Properties jpaProperties) { 103 CollectionUtils.mergePropertiesIntoMap(jpaProperties, this.jpaPropertyMap); 104 } 105 106 /** 107 * Specify JPA properties as a Map, to be passed into 108 * <code>EntityManagerFactory.createEntityManager(Map)</code> (if any). 109 * <p>Can be populated with a "map" or "props" element in XML bean definitions. 110 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 111 */ setJpaPropertyMap(Map<String, Object> jpaProperties)112 public void setJpaPropertyMap(Map<String, Object> jpaProperties) { 113 if (jpaProperties != null) { 114 this.jpaPropertyMap.putAll(jpaProperties); 115 } 116 } 117 118 /** 119 * Allow Map access to the JPA properties to be passed to the persistence 120 * provider, with the option to add or override specific entries. 121 * <p>Useful for specifying entries directly, for example via "jpaPropertyMap[myKey]". 122 */ getJpaPropertyMap()123 public Map<String, Object> getJpaPropertyMap() { 124 return this.jpaPropertyMap; 125 } 126 127 /** 128 * Retrieves an EntityManagerFactory by persistence unit name, if none set explicitly. 129 * Falls back to a default EntityManagerFactory bean if no persistence unit specified. 130 * @see #setPersistenceUnitName 131 */ setBeanFactory(BeanFactory beanFactory)132 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 133 if (getEntityManagerFactory() == null) { 134 if (!(beanFactory instanceof ListableBeanFactory)) { 135 throw new IllegalStateException("Cannot retrieve EntityManagerFactory by persistence unit name " + 136 "in a non-listable BeanFactory: " + beanFactory); 137 } 138 ListableBeanFactory lbf = (ListableBeanFactory) beanFactory; 139 setEntityManagerFactory(EntityManagerFactoryUtils.findEntityManagerFactory(lbf, getPersistenceUnitName())); 140 } 141 } 142 143 144 /** 145 * Obtain a new EntityManager from this accessor's EntityManagerFactory. 146 * <p>Can be overridden in subclasses to create specific EntityManager variants. 147 * @return a new EntityManager 148 * @throws IllegalStateException if this accessor is not configured with an EntityManagerFactory 149 * @see javax.persistence.EntityManagerFactory#createEntityManager() 150 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 151 */ createEntityManager()152 protected EntityManager createEntityManager() throws IllegalStateException { 153 EntityManagerFactory emf = getEntityManagerFactory(); 154 Assert.state(emf != null, "No EntityManagerFactory specified"); 155 Map<String, Object> properties = getJpaPropertyMap(); 156 return (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager()); 157 } 158 159 /** 160 * Obtain the transactional EntityManager for this accessor's EntityManagerFactory, if any. 161 * @return the transactional EntityManager, or <code>null</code> if none 162 * @throws IllegalStateException if this accessor is not configured with an EntityManagerFactory 163 * @see EntityManagerFactoryUtils#getTransactionalEntityManager(javax.persistence.EntityManagerFactory) 164 * @see EntityManagerFactoryUtils#getTransactionalEntityManager(javax.persistence.EntityManagerFactory, java.util.Map) 165 */ getTransactionalEntityManager()166 protected EntityManager getTransactionalEntityManager() throws IllegalStateException{ 167 EntityManagerFactory emf = getEntityManagerFactory(); 168 Assert.state(emf != null, "No EntityManagerFactory specified"); 169 return EntityManagerFactoryUtils.getTransactionalEntityManager(emf, getJpaPropertyMap()); 170 } 171 172 } 173