001/* 002 * Copyright 2002-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.orm.jpa; 018 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Properties; 022import javax.persistence.EntityManager; 023import javax.persistence.EntityManagerFactory; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027 028import org.springframework.beans.BeansException; 029import org.springframework.beans.factory.BeanFactory; 030import org.springframework.beans.factory.BeanFactoryAware; 031import org.springframework.beans.factory.ListableBeanFactory; 032import org.springframework.util.Assert; 033import org.springframework.util.CollectionUtils; 034 035/** 036 * Base class for any class that needs to access a JPA {@link EntityManagerFactory}, 037 * usually in order to obtain a JPA {@link EntityManager}. Defines common properties. 038 * 039 * @author Juergen Hoeller 040 * @since 2.0 041 * @see EntityManagerFactoryUtils 042 */ 043public abstract class EntityManagerFactoryAccessor implements BeanFactoryAware { 044 045 /** Logger available to subclasses */ 046 protected final Log logger = LogFactory.getLog(getClass()); 047 048 private EntityManagerFactory entityManagerFactory; 049 050 private String persistenceUnitName; 051 052 private final Map<String, Object> jpaPropertyMap = new HashMap<String, Object>(); 053 054 055 /** 056 * Set the JPA EntityManagerFactory that should be used to create 057 * EntityManagers. 058 * @see javax.persistence.EntityManagerFactory#createEntityManager() 059 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 060 */ 061 public void setEntityManagerFactory(EntityManagerFactory emf) { 062 this.entityManagerFactory = emf; 063 } 064 065 /** 066 * Return the JPA EntityManagerFactory that should be used to create 067 * EntityManagers. 068 */ 069 public EntityManagerFactory getEntityManagerFactory() { 070 return this.entityManagerFactory; 071 } 072 073 /** 074 * Set the name of the persistence unit to access the EntityManagerFactory for. 075 * <p>This is an alternative to specifying the EntityManagerFactory by direct reference, 076 * resolving it by its persistence unit name instead. If no EntityManagerFactory and 077 * no persistence unit name have been specified, a default EntityManagerFactory will 078 * be retrieved through finding a single unique bean of type EntityManagerFactory. 079 * @see #setEntityManagerFactory 080 */ 081 public void setPersistenceUnitName(String persistenceUnitName) { 082 this.persistenceUnitName = persistenceUnitName; 083 } 084 085 /** 086 * Return the name of the persistence unit to access the EntityManagerFactory for, if any. 087 */ 088 public String getPersistenceUnitName() { 089 return this.persistenceUnitName; 090 } 091 092 /** 093 * Specify JPA properties, to be passed into 094 * {@code EntityManagerFactory.createEntityManager(Map)} (if any). 095 * <p>Can be populated with a String "value" (parsed via PropertiesEditor) 096 * or a "props" element in XML bean definitions. 097 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 098 */ 099 public void setJpaProperties(Properties jpaProperties) { 100 CollectionUtils.mergePropertiesIntoMap(jpaProperties, this.jpaPropertyMap); 101 } 102 103 /** 104 * Specify JPA properties as a Map, to be passed into 105 * {@code EntityManagerFactory.createEntityManager(Map)} (if any). 106 * <p>Can be populated with a "map" or "props" element in XML bean definitions. 107 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 108 */ 109 public void setJpaPropertyMap(Map<String, Object> jpaProperties) { 110 if (jpaProperties != null) { 111 this.jpaPropertyMap.putAll(jpaProperties); 112 } 113 } 114 115 /** 116 * Allow Map access to the JPA properties to be passed to the persistence 117 * provider, with the option to add or override specific entries. 118 * <p>Useful for specifying entries directly, for example via "jpaPropertyMap[myKey]". 119 */ 120 public Map<String, Object> getJpaPropertyMap() { 121 return this.jpaPropertyMap; 122 } 123 124 /** 125 * Retrieves an EntityManagerFactory by persistence unit name, if none set explicitly. 126 * Falls back to a default EntityManagerFactory bean if no persistence unit specified. 127 * @see #setPersistenceUnitName 128 */ 129 @Override 130 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 131 if (getEntityManagerFactory() == null) { 132 if (!(beanFactory instanceof ListableBeanFactory)) { 133 throw new IllegalStateException("Cannot retrieve EntityManagerFactory by persistence unit name " + 134 "in a non-listable BeanFactory: " + beanFactory); 135 } 136 ListableBeanFactory lbf = (ListableBeanFactory) beanFactory; 137 setEntityManagerFactory(EntityManagerFactoryUtils.findEntityManagerFactory(lbf, getPersistenceUnitName())); 138 } 139 } 140 141 142 /** 143 * Obtain a new EntityManager from this accessor's EntityManagerFactory. 144 * <p>Can be overridden in subclasses to create specific EntityManager variants. 145 * @return a new EntityManager 146 * @throws IllegalStateException if this accessor is not configured with an EntityManagerFactory 147 * @see javax.persistence.EntityManagerFactory#createEntityManager() 148 * @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map) 149 */ 150 protected EntityManager createEntityManager() throws IllegalStateException { 151 EntityManagerFactory emf = getEntityManagerFactory(); 152 Assert.state(emf != null, "No EntityManagerFactory specified"); 153 Map<String, Object> properties = getJpaPropertyMap(); 154 return (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager()); 155 } 156 157 /** 158 * Obtain the transactional EntityManager for this accessor's EntityManagerFactory, if any. 159 * @return the transactional EntityManager, or {@code null} if none 160 * @throws IllegalStateException if this accessor is not configured with an EntityManagerFactory 161 * @see EntityManagerFactoryUtils#getTransactionalEntityManager(javax.persistence.EntityManagerFactory) 162 * @see EntityManagerFactoryUtils#getTransactionalEntityManager(javax.persistence.EntityManagerFactory, java.util.Map) 163 */ 164 protected EntityManager getTransactionalEntityManager() throws IllegalStateException{ 165 EntityManagerFactory emf = getEntityManagerFactory(); 166 Assert.state(emf != null, "No EntityManagerFactory specified"); 167 return EntityManagerFactoryUtils.getTransactionalEntityManager(emf, getJpaPropertyMap()); 168 } 169 170}