/** * Actually create the EntityManager proxy. * @param rawEm raw EntityManager * @param emIfc the (potentially vendor-specific) EntityManager * interface to proxy, or {@code null} for default detection of all interfaces * @param cl the ClassLoader to use for proxy creation (maybe {@code null}) * @param exceptionTranslator the PersistenceException translator to use * @param jta whether to create a JTA-aware EntityManager * (or {@code null} if not known in advance) * @param containerManaged whether to follow container-managed EntityManager * or application-managed EntityManager semantics * @param synchronizedWithTransaction whether to automatically join ongoing * transactions (according to the JPA 2.1 SynchronizationType rules) * @return the EntityManager proxy */ private static EntityManager createProxy( EntityManager rawEm, Class<? extends EntityManager> emIfc, ClassLoader cl, PersistenceExceptionTranslator exceptionTranslator, Boolean jta, boolean containerManaged, boolean synchronizedWithTransaction) { Assert.notNull(rawEm, "EntityManager must not be null"); Set<Class<?>> ifcs = new LinkedHashSet<Class<?>>(); if (emIfc != null) { ifcs.add(emIfc); } else { ifcs.addAll(ClassUtils.getAllInterfacesForClassAsSet(rawEm.getClass(), cl)); } ifcs.add(EntityManagerProxy.class); return (EntityManager) Proxy.newProxyInstance( (cl != null ? cl : ExtendedEntityManagerCreator.class.getClassLoader()), ifcs.toArray(new Class<?>[ifcs.size()]), new ExtendedEntityManagerInvocationHandler( rawEm, exceptionTranslator, jta, containerManaged, synchronizedWithTransaction)); }
/** * Actually create the EntityManager proxy. * @param rawEm raw EntityManager * @param emIfc the (potentially vendor-specific) EntityManager * interface to proxy, or {@code null} for default detection of all interfaces * @param plusOperations an implementation of the EntityManagerPlusOperations * interface, if those operations should be exposed (may be {@code null}) * @param exceptionTranslator the PersistenceException translator to use * @param jta whether to create a JTA-aware EntityManager * (or {@code null} if not known in advance) * @param containerManaged whether to follow container-managed EntityManager * or application-managed EntityManager semantics * @return the EntityManager proxy */ private static EntityManager createProxy( EntityManager rawEm, Class<? extends EntityManager> emIfc, ClassLoader cl, EntityManagerPlusOperations plusOperations, PersistenceExceptionTranslator exceptionTranslator, Boolean jta, boolean containerManaged) { Assert.notNull(rawEm, "EntityManager must not be null"); Set<Class> ifcs = new LinkedHashSet<Class>(); if (emIfc != null) { ifcs.add(emIfc); } else { ifcs.addAll(ClassUtils.getAllInterfacesForClassAsSet(rawEm.getClass(), cl)); } ifcs.add(EntityManagerProxy.class); if (plusOperations != null) { ifcs.add(EntityManagerPlusOperations.class); } return (EntityManager) Proxy.newProxyInstance( (cl != null ? cl : ExtendedEntityManagerCreator.class.getClassLoader()), ifcs.toArray(new Class[ifcs.size()]), new ExtendedEntityManagerInvocationHandler( rawEm, plusOperations, exceptionTranslator, jta, containerManaged)); }
/** * Create a new PersistenceExceptionTranslationAdvisor. * @param persistenceExceptionTranslator the PersistenceExceptionTranslator to use * @param repositoryAnnotationType the annotation type to check for */ public PersistenceExceptionTranslationAdvisor( PersistenceExceptionTranslator persistenceExceptionTranslator, Class<? extends Annotation> repositoryAnnotationType) { this.advice = new PersistenceExceptionTranslationInterceptor(persistenceExceptionTranslator); this.pointcut = new AnnotationMatchingPointcut(repositoryAnnotationType, true); }
private ExtendedEntityManagerInvocationHandler(EntityManager target, PersistenceExceptionTranslator exceptionTranslator, Boolean jta, boolean containerManaged, boolean synchronizedWithTransaction) { this.target = target; this.exceptionTranslator = exceptionTranslator; this.jta = (jta != null ? jta : isJtaEntityManager()); this.containerManaged = containerManaged; this.synchronizedWithTransaction = synchronizedWithTransaction; }
protected void doTestExceptionTranslationWithDialectFound(PersistenceExceptionTranslator pet) throws Exception { RuntimeException in1 = new RuntimeException("in1"); PersistenceException in2 = new PersistenceException(); assertNull("No translation here", pet.translateExceptionIfPossible(in1)); DataAccessException dex = pet.translateExceptionIfPossible(in2); assertNotNull(dex); assertSame(in2, dex.getCause()); }
@Override protected void addPersistenceExceptionTranslation(ProxyFactory pf, PersistenceExceptionTranslator pet) { if (AnnotationUtils.findAnnotation(pf.getTargetClass(), Repository.class) != null) { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); bf.registerBeanDefinition("peti", new RootBeanDefinition(PersistenceExceptionTranslationInterceptor.class)); bf.registerSingleton("pet", pet); pf.addAdvice((PersistenceExceptionTranslationInterceptor) bf.getBean("peti")); } }
public CustomSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { super(sqlSessionFactory, executorType, exceptionTranslator); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); this.defaultTargetSqlSessionFactory = sqlSessionFactory; }
/** * Constructs a Spring managed {@code SqlSession} with the given {@code SqlSessionFactory} and {@code ExecutorType}. * A custom {@code SQLExceptionTranslator} can be provided as an argument so any {@code PersistenceException} thrown * by MyBatis can be custom translated to a {@code RuntimeException} The {@code SQLExceptionTranslator} can also be * null and thus no exception translation will be done and MyBatis exceptions will be thrown * * @param sqlSessionFactory * @param executorType * @param exceptionTranslator */ public SimpleSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { super(sqlSessionFactory); notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.defaultSqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); }
/** * Constructs a Spring managed {@code SqlSession} with the given * {@code SqlSessionFactory} and {@code ExecutorType}. * A custom {@code SQLExceptionTranslator} can be provided as an * argument so any {@code PersistenceException} thrown by MyBatis * can be custom translated to a {@code RuntimeException} * The {@code SQLExceptionTranslator} can also be null and thus no * exception translation will be done and MyBatis exceptions will be * thrown * * @param sqlSessionFactory * @param executorType * @param exceptionTranslator */ public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); }
/** * Creates a new holder instance. * * @param sqlSession the {@code SqlSession} has to be hold. * @param executorType the {@code ExecutorType} has to be hold. */ public SqlSessionHolder(SqlSession sqlSession, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSession, "SqlSession must not be null"); notNull(executorType, "ExecutorType must not be null"); this.sqlSession = sqlSession; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; }
/** * Gets any {@link PersistenceExceptionTranslator}s from the {@link BeanFactory}. * * @param beanFactory The {@link BeanFactory} to use. * * @return A {@link PersistenceExceptionTranslator} from the {@link BeanFactory}. */ protected PersistenceExceptionTranslator detectPersistenceExceptionTranslators(ListableBeanFactory beanFactory) { // Find all translators, being careful not to activate FactoryBeans. Map<String, PersistenceExceptionTranslator> pets = BeanFactoryUtils.beansOfTypeIncludingAncestors(beanFactory, PersistenceExceptionTranslator.class, false, false); ChainedPersistenceExceptionTranslator cpet = new ChainedPersistenceExceptionTranslator(); for (PersistenceExceptionTranslator pet : pets.values()) { cpet.addDelegate(pet); } // always add one last persistence exception translator as a catch all cpet.addDelegate(new DefaultPersistenceExceptionTranslator()); return cpet; }
private void registerPersistenceExceptionTranslator() { if (this.applicationContext != null && this.applicationContext.getBeansOfType(PersistenceExceptionTranslator.class).isEmpty()) { if (this.applicationContext instanceof ConfigurableApplicationContext) { ((ConfigurableApplicationContext) this.applicationContext).getBeanFactory().registerSingleton( "solrExceptionTranslator", EXCEPTION_TRANSLATOR); } } }
@Bean public PersistenceExceptionTranslator persistenceExceptionTranslator() { return new PersistenceExceptionTranslator() { @Override public DataAccessException translateExceptionIfPossible(RuntimeException e) { return null; } }; }
private ExtendedEntityManagerInvocationHandler( EntityManager target, EntityManagerPlusOperations plusOperations, PersistenceExceptionTranslator exceptionTranslator, Boolean jta, boolean containerManaged) { this.target = target; this.plusOperations = plusOperations; this.exceptionTranslator = exceptionTranslator; this.jta = (jta != null ? jta : isJtaEntityManager()); this.containerManaged = containerManaged; }
@Override @Bean public MongoDbFactory mongoDbFactory() { return new SimpleMongoDbFactory(mongo, getDatabaseName(), getUserCredentials(), getAuthenticationDatabaseName()) { @Override public PersistenceExceptionTranslator getExceptionTranslator() { return MongoTemplateWithRetry.getExceptionTranslator(); } }; }
public PersistenceExceptionTranslator getPersistenceExceptionTranslator() { return this.exceptionTranslator; }
public ExtendedEntityManagerSynchronization( EntityManager em, PersistenceExceptionTranslator exceptionTranslator) { super(new EntityManagerHolder(em), em); this.entityManager = em; this.exceptionTranslator = exceptionTranslator; }
@Override public PersistenceExceptionTranslator getExceptionTranslator() { return null; }
protected void addPersistenceExceptionTranslation(ProxyFactory pf, PersistenceExceptionTranslator pet) { pf.addAdvisor(new PersistenceExceptionTranslationAdvisor(pet, Repository.class)); }
@Bean public PersistenceExceptionTranslator peTranslator() { PersistenceExceptionTranslator txlator = mock(PersistenceExceptionTranslator.class); return txlator; }
@Override public PersistenceExceptionTranslator getExceptionTranslator() { return this.mongoDbFactory.getExceptionTranslator(); }
/** * Gets an SqlSession from Spring Transaction Manager or creates a new one if needed. * Tries to get a SqlSession out of current transaction. If there is not any, it creates a new one. * Then, it synchronizes the SqlSession with the transaction if Spring TX is active and * <code>SpringManagedTransactionFactory</code> is configured as a transaction manager. * * @param sessionFactory a MyBatis {@code SqlSessionFactory} to create new sessions * @param executorType The executor type of the SqlSession to create * @param exceptionTranslator Optional. Translates SqlSession.commit() exceptions to Spring exceptions. * @throws TransientDataAccessResourceException if a transaction is active and the * {@code SqlSessionFactory} is not using a {@code SpringManagedTransactionFactory} * @see SpringManagedTransactionFactory */ public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sessionFactory, "No SqlSessionFactory specified"); notNull(executorType, "No ExecutorType specified"); SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); if (holder != null && holder.isSynchronizedWithTransaction()) { if (holder.getExecutorType() != executorType) { throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction"); } holder.requested(); if (logger.isDebugEnabled()) { logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction"); } return holder.getSqlSession(); } if (logger.isDebugEnabled()) { logger.debug("Creating a new SqlSession"); } SqlSession session = sessionFactory.openSession(executorType); // Register session holder if synchronization is active (i.e. a Spring TX is active) // // Note: The DataSource used by the Environment should be synchronized with the // transaction either through DataSourceTxMgr or another tx synchronization. // Further assume that if an exception is thrown, whatever started the transaction will // handle closing / rolling back the Connection associated with the SqlSession. if (TransactionSynchronizationManager.isSynchronizationActive()) { Environment environment = sessionFactory.getConfiguration().getEnvironment(); if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) { if (logger.isDebugEnabled()) { logger.debug("Registering transaction synchronization for SqlSession [" + session + "]"); } holder = new SqlSessionHolder(session, executorType, exceptionTranslator); TransactionSynchronizationManager.bindResource(sessionFactory, holder); TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory)); holder.setSynchronizedWithTransaction(true); holder.requested(); } else { if (TransactionSynchronizationManager.getResource(environment.getDataSource()) == null) { if (logger.isDebugEnabled()) { logger.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional"); } } else { throw new TransientDataAccessResourceException( "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization"); } } } else { if (logger.isDebugEnabled()) { logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active"); } } return session; }