1 16 17 package org.springframework.orm.jpa; 18 19 import java.util.Map ; 20 21 import javax.persistence.EntityExistsException; 22 import javax.persistence.EntityManager; 23 import javax.persistence.EntityManagerFactory; 24 import javax.persistence.EntityNotFoundException; 25 import javax.persistence.NoResultException; 26 import javax.persistence.NonUniqueResultException; 27 import javax.persistence.OptimisticLockException; 28 import javax.persistence.PersistenceException; 29 import javax.persistence.TransactionRequiredException; 30 31 import org.apache.commons.logging.Log; 32 import org.apache.commons.logging.LogFactory; 33 34 import org.springframework.dao.DataAccessException; 35 import org.springframework.dao.DataAccessResourceFailureException; 36 import org.springframework.dao.DataIntegrityViolationException; 37 import org.springframework.dao.EmptyResultDataAccessException; 38 import org.springframework.dao.IncorrectResultSizeDataAccessException; 39 import org.springframework.dao.InvalidDataAccessApiUsageException; 40 import org.springframework.jdbc.datasource.DataSourceUtils; 41 import org.springframework.transaction.support.TransactionSynchronizationAdapter; 42 import org.springframework.transaction.support.TransactionSynchronizationManager; 43 import org.springframework.util.Assert; 44 import org.springframework.util.CollectionUtils; 45 46 56 public abstract class EntityManagerFactoryUtils { 57 58 64 public static final int ENTITY_MANAGER_SYNCHRONIZATION_ORDER = 65 DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100; 66 67 private static final Log logger = LogFactory.getLog(EntityManagerFactoryUtils.class); 68 69 70 80 public static EntityManager getTransactionalEntityManager(EntityManagerFactory emf) 81 throws DataAccessResourceFailureException { 82 83 return getTransactionalEntityManager(emf, null); 84 } 85 86 98 public static EntityManager getTransactionalEntityManager(EntityManagerFactory emf, Map properties) 99 throws DataAccessResourceFailureException { 100 try { 101 return doGetTransactionalEntityManager(emf, properties); 102 } 103 catch (PersistenceException ex) { 104 throw new DataAccessResourceFailureException("Could not obtain JPA EntityManager", ex); 105 } 106 } 107 108 121 public static EntityManager doGetTransactionalEntityManager( 122 EntityManagerFactory emf, Map properties) throws PersistenceException { 123 124 Assert.notNull(emf, "No EntityManagerFactory specified"); 125 126 EntityManagerHolder emHolder = 127 (EntityManagerHolder) TransactionSynchronizationManager.getResource(emf); 128 if (emHolder != null) { 129 if (!emHolder.isSynchronizedWithTransaction() && 130 TransactionSynchronizationManager.isSynchronizationActive()) { 131 try { 134 emHolder.getEntityManager().joinTransaction(); 135 } 136 catch (TransactionRequiredException ex) { 137 logger.debug("Could not join JTA transaction because none was active", ex); 138 } 139 emHolder.setSynchronizedWithTransaction(true); 140 TransactionSynchronizationManager.registerSynchronization( 141 new EntityManagerSynchronization(emHolder, emf, false)); 142 } 143 return emHolder.getEntityManager(); 144 } 145 146 if (!TransactionSynchronizationManager.isSynchronizationActive()) { 147 return null; 149 } 150 151 logger.debug("Opening JPA EntityManager"); 153 EntityManager em = 154 (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager()); 155 156 if (TransactionSynchronizationManager.isSynchronizationActive()) { 157 logger.debug("Registering transaction synchronization for JPA EntityManager"); 158 emHolder = new EntityManagerHolder(em); 161 emHolder.setSynchronizedWithTransaction(true); 162 TransactionSynchronizationManager.registerSynchronization( 163 new EntityManagerSynchronization(emHolder, emf, true)); 164 TransactionSynchronizationManager.bindResource(emf, emHolder); 165 } 166 167 return em; 168 } 169 170 183 public static DataAccessException convertJpaAccessExceptionIfPossible(RuntimeException ex) { 184 if (ex instanceof IllegalStateException ) { 187 return new InvalidDataAccessApiUsageException(ex.getMessage(), ex); 188 } 189 if (ex instanceof IllegalArgumentException ) { 190 return new InvalidDataAccessApiUsageException(ex.getMessage(), ex); 191 } 192 193 if (ex instanceof EntityNotFoundException) { 195 return new JpaObjectRetrievalFailureException((EntityNotFoundException) ex); 196 } 197 if (ex instanceof NoResultException) { 198 return new EmptyResultDataAccessException(ex.getMessage(), 1); 199 } 200 if (ex instanceof NonUniqueResultException) { 201 return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1); 202 } 203 if (ex instanceof OptimisticLockException) { 204 return new JpaOptimisticLockingFailureException((OptimisticLockException) ex); 205 } 206 if (ex instanceof EntityExistsException) { 207 return new DataIntegrityViolationException(ex.getMessage(), ex); 208 } 209 if (ex instanceof TransactionRequiredException) { 210 return new InvalidDataAccessApiUsageException(ex.getMessage(), ex); 211 } 212 213 if (ex instanceof PersistenceException) { 215 return new JpaSystemException((PersistenceException) ex); 216 } 217 218 return null; 222 } 223 224 225 230 private static class EntityManagerSynchronization extends TransactionSynchronizationAdapter { 231 232 private final EntityManagerHolder entityManagerHolder; 233 234 private final EntityManagerFactory entityManagerFactory; 235 236 private final boolean newEntityManager; 237 238 private boolean holderActive = true; 239 240 public EntityManagerSynchronization( 241 EntityManagerHolder emHolder, EntityManagerFactory emf, boolean newEntityManager) { 242 this.entityManagerHolder = emHolder; 243 this.entityManagerFactory = emf; 244 this.newEntityManager = newEntityManager; 245 } 246 247 public int getOrder() { 248 return ENTITY_MANAGER_SYNCHRONIZATION_ORDER; 249 } 250 251 public void suspend() { 252 if (this.holderActive) { 253 TransactionSynchronizationManager.unbindResource(this.entityManagerFactory); 254 } 255 } 256 257 public void resume() { 258 if (this.holderActive) { 259 TransactionSynchronizationManager.bindResource(this.entityManagerFactory, this.entityManagerHolder); 260 } 261 } 262 263 public void beforeCompletion() { 264 if (this.newEntityManager) { 265 TransactionSynchronizationManager.unbindResource(this.entityManagerFactory); 266 this.holderActive = false; 267 this.entityManagerHolder.getEntityManager().close(); 268 } 269 } 270 271 public void afterCompletion(int status) { 272 if (!this.newEntityManager && status != STATUS_COMMITTED) { 273 this.entityManagerHolder.getEntityManager().clear(); 276 } 277 this.entityManagerHolder.setSynchronizedWithTransaction(false); 278 } 279 } 280 281 } 282 | Popular Tags |