001/* 002 * Copyright 2002-2017 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.support; 018 019import javax.persistence.EntityManager; 020import javax.persistence.EntityManagerFactory; 021 022import org.springframework.beans.factory.FactoryBean; 023import org.springframework.beans.factory.InitializingBean; 024import org.springframework.orm.jpa.EntityManagerFactoryAccessor; 025import org.springframework.orm.jpa.EntityManagerFactoryInfo; 026import org.springframework.orm.jpa.SharedEntityManagerCreator; 027import org.springframework.util.Assert; 028 029/** 030 * {@link FactoryBean} that exposes a shared JPA {@link javax.persistence.EntityManager} 031 * reference for a given EntityManagerFactory. Typically used for an EntityManagerFactory 032 * created by {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}, 033 * as direct alternative to a JNDI lookup for a Java EE server's EntityManager reference. 034 * 035 * <p>The shared EntityManager will behave just like an EntityManager fetched from an 036 * application server's JNDI environment, as defined by the JPA specification. 037 * It will delegate all calls to the current transactional EntityManager, if any; 038 * otherwise, it will fall back to a newly created EntityManager per operation. 039 * 040 * <p>Can be passed to DAOs that expect a shared EntityManager reference rather than an 041 * EntityManagerFactory. Note that Spring's {@link org.springframework.orm.jpa.JpaTransactionManager} 042 * always needs an EntityManagerFactory in order to create new transactional EntityManager instances. 043 * 044 * @author Juergen Hoeller 045 * @since 2.0 046 * @see #setEntityManagerFactory 047 * @see #setEntityManagerInterface 048 * @see org.springframework.orm.jpa.LocalEntityManagerFactoryBean 049 * @see org.springframework.orm.jpa.JpaTransactionManager 050 */ 051public class SharedEntityManagerBean extends EntityManagerFactoryAccessor 052 implements FactoryBean<EntityManager>, InitializingBean { 053 054 private Class<? extends EntityManager> entityManagerInterface; 055 056 private boolean synchronizedWithTransaction = true; 057 058 private EntityManager shared; 059 060 061 /** 062 * Specify the EntityManager interface to expose. 063 * <p>Default is the EntityManager interface as defined by the 064 * EntityManagerFactoryInfo, if available. Else, the standard 065 * {@code javax.persistence.EntityManager} interface will be used. 066 * @see org.springframework.orm.jpa.EntityManagerFactoryInfo#getEntityManagerInterface() 067 * @see javax.persistence.EntityManager 068 */ 069 public void setEntityManagerInterface(Class<? extends EntityManager> entityManagerInterface) { 070 Assert.notNull(entityManagerInterface, "'entityManagerInterface' must not be null"); 071 this.entityManagerInterface = entityManagerInterface; 072 } 073 074 /** 075 * Set whether to automatically join ongoing transactions (according 076 * to the JPA 2.1 SynchronizationType rules). Default is "true". 077 */ 078 public void setSynchronizedWithTransaction(boolean synchronizedWithTransaction) { 079 this.synchronizedWithTransaction = synchronizedWithTransaction; 080 } 081 082 083 @Override 084 public final void afterPropertiesSet() { 085 EntityManagerFactory emf = getEntityManagerFactory(); 086 if (emf == null) { 087 throw new IllegalArgumentException("'entityManagerFactory' or 'persistenceUnitName' is required"); 088 } 089 if (emf instanceof EntityManagerFactoryInfo) { 090 EntityManagerFactoryInfo emfInfo = (EntityManagerFactoryInfo) emf; 091 if (this.entityManagerInterface == null) { 092 this.entityManagerInterface = emfInfo.getEntityManagerInterface(); 093 if (this.entityManagerInterface == null) { 094 this.entityManagerInterface = EntityManager.class; 095 } 096 } 097 } 098 else { 099 if (this.entityManagerInterface == null) { 100 this.entityManagerInterface = EntityManager.class; 101 } 102 } 103 this.shared = SharedEntityManagerCreator.createSharedEntityManager( 104 emf, getJpaPropertyMap(), this.synchronizedWithTransaction, this.entityManagerInterface); 105 } 106 107 108 @Override 109 public EntityManager getObject() { 110 return this.shared; 111 } 112 113 @Override 114 public Class<? extends EntityManager> getObjectType() { 115 return (this.entityManagerInterface != null ? this.entityManagerInterface : EntityManager.class); 116 } 117 118 @Override 119 public boolean isSingleton() { 120 return true; 121 } 122 123}