mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
Polishing
This commit is contained in:
+7
-5
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,21 +20,23 @@ import org.springframework.beans.BeansException;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when a {@code BeanFactory} is asked for a bean instance
|
* Exception thrown when a {@code BeanFactory} is asked for a bean instance for which it
|
||||||
* for which it cannot find a definition.
|
* cannot find a definition. This may point to a non-existing bean, a non-unique bean,
|
||||||
|
* or a manually registered singleton instance without an associated bean definition.
|
||||||
*
|
*
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @see BeanFactory#getBean(String)
|
* @see BeanFactory#getBean(String)
|
||||||
* @see BeanFactory#getBean(Class)
|
* @see BeanFactory#getBean(Class)
|
||||||
|
* @see NoUniqueBeanDefinitionException
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class NoSuchBeanDefinitionException extends BeansException {
|
public class NoSuchBeanDefinitionException extends BeansException {
|
||||||
|
|
||||||
/** Name of the missing bean. */
|
/** Name of the missing bean */
|
||||||
private String beanName;
|
private String beanName;
|
||||||
|
|
||||||
/** Required type of the missing bean. */
|
/** Required type of the missing bean */
|
||||||
private Class<?> beanType;
|
private Class<?> beanType;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -140,14 +140,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||||||
/** Map of bean definition objects, keyed by bean name */
|
/** Map of bean definition objects, keyed by bean name */
|
||||||
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
|
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
|
||||||
|
|
||||||
/** Map of singleton and non-singleton bean names keyed by dependency type */
|
/** Map of singleton and non-singleton bean names, keyed by dependency type */
|
||||||
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
|
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
|
||||||
|
|
||||||
/** Map of singleton-only bean names keyed by dependency type */
|
/** Map of singleton-only bean names, keyed by dependency type */
|
||||||
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
|
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
|
||||||
|
|
||||||
/** List of bean definition names, in registration order */
|
/** List of bean definition names, in registration order */
|
||||||
private final List<String> beanDefinitionNames = new ArrayList<String>();
|
private final List<String> beanDefinitionNames = new ArrayList<String>(64);
|
||||||
|
|
||||||
/** Whether bean definition metadata may be cached for all beans */
|
/** Whether bean definition metadata may be cached for all beans */
|
||||||
private boolean configurationFrozen = false;
|
private boolean configurationFrozen = false;
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -76,7 +76,7 @@ public class DelegatingConnectionFactory
|
|||||||
/**
|
/**
|
||||||
* Indicate whether Connections obtained from the target factory are supposed
|
* Indicate whether Connections obtained from the target factory are supposed
|
||||||
* to be stopped before closed ("true") or simply closed ("false").
|
* to be stopped before closed ("true") or simply closed ("false").
|
||||||
* The latter may be necessary for some connection pools that simply return
|
* An extra stop call may be necessary for some connection pools that simply return
|
||||||
* released connections to the pool, not stopping them while they sit in the pool.
|
* released connections to the pool, not stopping them while they sit in the pool.
|
||||||
* <p>Default is "false", simply closing Connections.
|
* <p>Default is "false", simply closing Connections.
|
||||||
* @see ConnectionFactoryUtils#releaseConnection
|
* @see ConnectionFactoryUtils#releaseConnection
|
||||||
|
|||||||
+6
-5
@@ -73,9 +73,8 @@ import org.springframework.util.Assert;
|
|||||||
* @see org.springframework.jms.listener.SimpleMessageListenerContainer
|
* @see org.springframework.jms.listener.SimpleMessageListenerContainer
|
||||||
* @see org.springframework.jms.listener.DefaultMessageListenerContainer#setCacheLevel
|
* @see org.springframework.jms.listener.DefaultMessageListenerContainer#setCacheLevel
|
||||||
*/
|
*/
|
||||||
public class SingleConnectionFactory
|
public class SingleConnectionFactory implements ConnectionFactory, QueueConnectionFactory,
|
||||||
implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, ExceptionListener,
|
TopicConnectionFactory, ExceptionListener, InitializingBean, DisposableBean {
|
||||||
InitializingBean, DisposableBean {
|
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
@@ -171,7 +170,7 @@ public class SingleConnectionFactory
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify an JMS ExceptionListener implementation that should be
|
* Specify an JMS ExceptionListener implementation that should be
|
||||||
* registered with with the single Connection created by this factory.
|
* registered with the single Connection created by this factory.
|
||||||
* @see #setReconnectOnException
|
* @see #setReconnectOnException
|
||||||
*/
|
*/
|
||||||
public void setExceptionListener(ExceptionListener exceptionListener) {
|
public void setExceptionListener(ExceptionListener exceptionListener) {
|
||||||
@@ -180,7 +179,7 @@ public class SingleConnectionFactory
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the JMS ExceptionListener implementation that should be registered
|
* Return the JMS ExceptionListener implementation that should be registered
|
||||||
* with with the single Connection created by this factory, if any.
|
* with the single Connection created by this factory, if any.
|
||||||
*/
|
*/
|
||||||
protected ExceptionListener getExceptionListener() {
|
protected ExceptionListener getExceptionListener() {
|
||||||
return this.exceptionListener;
|
return this.exceptionListener;
|
||||||
@@ -315,6 +314,7 @@ public class SingleConnectionFactory
|
|||||||
* The provider of this ConnectionFactory needs to care for proper shutdown.
|
* The provider of this ConnectionFactory needs to care for proper shutdown.
|
||||||
* <p>As this bean implements DisposableBean, a bean factory will
|
* <p>As this bean implements DisposableBean, a bean factory will
|
||||||
* automatically invoke this on destruction of its cached singletons.
|
* automatically invoke this on destruction of its cached singletons.
|
||||||
|
* @see #resetConnection()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
@@ -323,6 +323,7 @@ public class SingleConnectionFactory
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the underlying shared Connection, to be reinitialized on next access.
|
* Reset the underlying shared Connection, to be reinitialized on next access.
|
||||||
|
* @see #closeConnection
|
||||||
*/
|
*/
|
||||||
public void resetConnection() {
|
public void resetConnection() {
|
||||||
synchronized (this.connectionMonitor) {
|
synchronized (this.connectionMonitor) {
|
||||||
|
|||||||
+14
-13
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -38,8 +38,7 @@ import org.springframework.util.StringUtils;
|
|||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public final class DestinationPatternsMessageCondition
|
public class DestinationPatternsMessageCondition extends AbstractMessageCondition<DestinationPatternsMessageCondition> {
|
||||||
extends AbstractMessageCondition<DestinationPatternsMessageCondition> {
|
|
||||||
|
|
||||||
public static final String LOOKUP_DESTINATION_HEADER = "lookupDestination";
|
public static final String LOOKUP_DESTINATION_HEADER = "lookupDestination";
|
||||||
|
|
||||||
@@ -59,22 +58,22 @@ public final class DestinationPatternsMessageCondition
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional constructor with flags for using suffix pattern (.*) and
|
* Additional constructor with flags for using suffix pattern (.*) and trailing slash matches.
|
||||||
* trailing slash matches.
|
|
||||||
* @param patterns the URL patterns to use; if 0, the condition will match to every request.
|
* @param patterns the URL patterns to use; if 0, the condition will match to every request.
|
||||||
* @param pathMatcher for path matching with patterns
|
* @param pathMatcher the PathMatcher to use
|
||||||
*/
|
*/
|
||||||
public DestinationPatternsMessageCondition(String[] patterns,PathMatcher pathMatcher) {
|
public DestinationPatternsMessageCondition(String[] patterns, PathMatcher pathMatcher) {
|
||||||
this(asList(patterns), pathMatcher);
|
this(asList(patterns), pathMatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DestinationPatternsMessageCondition(Collection<String> patterns, PathMatcher pathMatcher) {
|
private DestinationPatternsMessageCondition(Collection<String> patterns, PathMatcher pathMatcher) {
|
||||||
this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns));
|
this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns));
|
||||||
this.pathMatcher = (pathMatcher != null) ? pathMatcher : new AntPathMatcher();
|
this.pathMatcher = (pathMatcher != null ? pathMatcher : new AntPathMatcher());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static List<String> asList(String... patterns) {
|
private static List<String> asList(String... patterns) {
|
||||||
return patterns != null ? Arrays.asList(patterns) : Collections.<String>emptyList();
|
return (patterns != null ? Arrays.asList(patterns) : Collections.<String>emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<String> prependLeadingSlash(Collection<String> patterns) {
|
private static Set<String> prependLeadingSlash(Collection<String> patterns) {
|
||||||
@@ -91,6 +90,7 @@ public final class DestinationPatternsMessageCondition
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Set<String> getPatterns() {
|
public Set<String> getPatterns() {
|
||||||
return this.patterns;
|
return this.patterns;
|
||||||
}
|
}
|
||||||
@@ -105,14 +105,15 @@ public final class DestinationPatternsMessageCondition
|
|||||||
return " || ";
|
return " || ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a new instance with URL patterns from the current instance ("this") and
|
* Returns a new instance with URL patterns from the current instance ("this") and
|
||||||
* the "other" instance as follows:
|
* the "other" instance as follows:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>If there are patterns in both instances, combine the patterns in "this" with
|
* <li>If there are patterns in both instances, combine the patterns in "this" with
|
||||||
* the patterns in "other" using {@link org.springframework.util.PathMatcher#combine(String, String)}.
|
* the patterns in "other" using {@link org.springframework.util.PathMatcher#combine(String, String)}.
|
||||||
* <li>If only one instance has patterns, use them.
|
* <li>If only one instance has patterns, use them.
|
||||||
* <li>If neither instance has patterns, use an empty String (i.e. "").
|
* <li>If neither instance has patterns, use an empty String (i.e. "").
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -241,7 +241,7 @@ public class LocalSessionFactoryBuilder extends Configuration {
|
|||||||
* @see #scanPackages
|
* @see #scanPackages
|
||||||
*/
|
*/
|
||||||
public LocalSessionFactoryBuilder addPackages(String... annotatedPackages) {
|
public LocalSessionFactoryBuilder addPackages(String... annotatedPackages) {
|
||||||
for (String annotatedPackage :annotatedPackages) {
|
for (String annotatedPackage : annotatedPackages) {
|
||||||
addPackage(annotatedPackage);
|
addPackage(annotatedPackage);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -28,7 +28,7 @@ import org.springframework.transaction.support.TransactionSynchronizationAdapter
|
|||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
class SpringFlushSynchronization extends TransactionSynchronizationAdapter {
|
public class SpringFlushSynchronization extends TransactionSynchronizationAdapter {
|
||||||
|
|
||||||
private final Session session;
|
private final Session session;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|||||||
+1
-1
@@ -70,7 +70,7 @@ import static org.mockito.BDDMockito.*;
|
|||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public class HibernateTransactionManagerTests {
|
public class HibernateTransactionManagerTests {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
+8
-8
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -55,15 +55,15 @@ import org.springframework.util.ClassUtils;
|
|||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract {@link org.springframework.beans.factory.FactoryBean} that
|
* Abstract {@link org.springframework.beans.factory.FactoryBean} that creates
|
||||||
* creates a local JPA {@link javax.persistence.EntityManagerFactory}
|
* a local JPA {@link javax.persistence.EntityManagerFactory} instance within
|
||||||
* instance within a Spring application context.
|
* a Spring application context.
|
||||||
*
|
*
|
||||||
* <p>Encapsulates the common functionality between the different JPA
|
* <p>Encapsulates the common functionality between the different JPA bootstrap
|
||||||
* bootstrap contracts (standalone as well as container).
|
* contracts (standalone as well as container).
|
||||||
*
|
*
|
||||||
* <p>Implements support for standard JPA configuration as well as
|
* <p>Implements support for standard JPA configuration conventions as well as
|
||||||
* Spring's {@link JpaVendorAdapter} abstraction, and controls the
|
* Spring's customizable {@link JpaVendorAdapter} mechanism, and controls the
|
||||||
* EntityManagerFactory's lifecycle.
|
* EntityManagerFactory's lifecycle.
|
||||||
*
|
*
|
||||||
* <p>This class also implements the
|
* <p>This class also implements the
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -33,8 +33,8 @@ import org.springframework.util.Assert;
|
|||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for any class that needs to access an EntityManagerFactory,
|
* Base class for any class that needs to access a JPA {@link EntityManagerFactory},
|
||||||
* usually in order to obtain an EntityManager. Defines common properties.
|
* usually in order to obtain a JPA {@link EntityManager}. Defines common properties.
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
|||||||
+13
-16
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -80,6 +80,7 @@ public abstract class EntityManagerFactoryUtils {
|
|||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(EntityManagerFactoryUtils.class);
|
private static final Log logger = LogFactory.getLog(EntityManagerFactoryUtils.class);
|
||||||
|
|
||||||
|
|
||||||
private static Method createEntityManagerWithSynchronizationTypeMethod;
|
private static Method createEntityManagerWithSynchronizationTypeMethod;
|
||||||
|
|
||||||
private static Object synchronizationTypeUnsynchronized;
|
private static Object synchronizationTypeUnsynchronized;
|
||||||
@@ -144,9 +145,8 @@ public abstract class EntityManagerFactoryUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a JPA EntityManager from the given factory. Is aware of a
|
* Obtain a JPA EntityManager from the given factory. Is aware of a corresponding
|
||||||
* corresponding EntityManager bound to the current thread,
|
* EntityManager bound to the current thread, e.g. when using JpaTransactionManager.
|
||||||
* for example when using JpaTransactionManager.
|
|
||||||
* <p>Note: Will return {@code null} if no thread-bound EntityManager found!
|
* <p>Note: Will return {@code null} if no thread-bound EntityManager found!
|
||||||
* @param emf EntityManagerFactory to create the EntityManager with
|
* @param emf EntityManagerFactory to create the EntityManager with
|
||||||
* @return the EntityManager, or {@code null} if none found
|
* @return the EntityManager, or {@code null} if none found
|
||||||
@@ -160,9 +160,8 @@ public abstract class EntityManagerFactoryUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a JPA EntityManager from the given factory. Is aware of a
|
* Obtain a JPA EntityManager from the given factory. Is aware of a corresponding
|
||||||
* corresponding EntityManager bound to the current thread,
|
* EntityManager bound to the current thread, e.g. when using JpaTransactionManager.
|
||||||
* for example when using JpaTransactionManager.
|
|
||||||
* <p>Note: Will return {@code null} if no thread-bound EntityManager found!
|
* <p>Note: Will return {@code null} if no thread-bound EntityManager found!
|
||||||
* @param emf EntityManagerFactory to create the EntityManager with
|
* @param emf EntityManagerFactory to create the EntityManager with
|
||||||
* @param properties the properties to be passed into the {@code createEntityManager}
|
* @param properties the properties to be passed into the {@code createEntityManager}
|
||||||
@@ -182,9 +181,8 @@ public abstract class EntityManagerFactoryUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a JPA EntityManager from the given factory. Is aware of a
|
* Obtain a JPA EntityManager from the given factory. Is aware of a corresponding
|
||||||
* corresponding EntityManager bound to the current thread,
|
* EntityManager bound to the current thread, e.g. when using JpaTransactionManager.
|
||||||
* for example when using JpaTransactionManager.
|
|
||||||
* <p>Same as {@code getEntityManager}, but throwing the original PersistenceException.
|
* <p>Same as {@code getEntityManager}, but throwing the original PersistenceException.
|
||||||
* @param emf EntityManagerFactory to create the EntityManager with
|
* @param emf EntityManagerFactory to create the EntityManager with
|
||||||
* @param properties the properties to be passed into the {@code createEntityManager}
|
* @param properties the properties to be passed into the {@code createEntityManager}
|
||||||
@@ -201,9 +199,8 @@ public abstract class EntityManagerFactoryUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain a JPA EntityManager from the given factory. Is aware of a
|
* Obtain a JPA EntityManager from the given factory. Is aware of a corresponding
|
||||||
* corresponding EntityManager bound to the current thread,
|
* EntityManager bound to the current thread, e.g. when using JpaTransactionManager.
|
||||||
* for example when using JpaTransactionManager.
|
|
||||||
* <p>Same as {@code getEntityManager}, but throwing the original PersistenceException.
|
* <p>Same as {@code getEntityManager}, but throwing the original PersistenceException.
|
||||||
* @param emf EntityManagerFactory to create the EntityManager with
|
* @param emf EntityManagerFactory to create the EntityManager with
|
||||||
* @param properties the properties to be passed into the {@code createEntityManager}
|
* @param properties the properties to be passed into the {@code createEntityManager}
|
||||||
@@ -285,8 +282,8 @@ public abstract class EntityManagerFactoryUtils {
|
|||||||
em = (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
|
em = (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use same EntityManager for further JPA actions within the transaction.
|
// Use same EntityManager for further JPA operations within the transaction.
|
||||||
// Thread object will get removed by synchronization at transaction completion.
|
// Thread-bound object will get removed by synchronization at transaction completion.
|
||||||
logger.debug("Registering transaction synchronization for JPA EntityManager");
|
logger.debug("Registering transaction synchronization for JPA EntityManager");
|
||||||
emHolder = new EntityManagerHolder(em);
|
emHolder = new EntityManagerHolder(em);
|
||||||
if (synchronizedWithTransaction) {
|
if (synchronizedWithTransaction) {
|
||||||
@@ -296,7 +293,7 @@ public abstract class EntityManagerFactoryUtils {
|
|||||||
emHolder.setSynchronizedWithTransaction(true);
|
emHolder.setSynchronizedWithTransaction(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// unsynchronized - just scope it for the transaction, as demanded by the JPA 2.1 spec
|
// Unsynchronized - just scope it for the transaction, as demanded by the JPA 2.1 spec...
|
||||||
TransactionSynchronizationManager.registerSynchronization(
|
TransactionSynchronizationManager.registerSynchronization(
|
||||||
new TransactionScopedEntityManagerSynchronization(emHolder, emf));
|
new TransactionScopedEntityManagerSynchronization(emHolder, emf));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||||||
* transactions (according to the JPA 2.1 SynchronizationType rules)
|
* transactions (according to the JPA 2.1 SynchronizationType rules)
|
||||||
* @return an application-managed EntityManager that can join transactions
|
* @return an application-managed EntityManager that can join transactions
|
||||||
* but does not participate in them automatically
|
* but does not participate in them automatically
|
||||||
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public static EntityManager createApplicationManagedEntityManager(
|
public static EntityManager createApplicationManagedEntityManager(
|
||||||
EntityManager rawEntityManager, EntityManagerFactoryInfo emfInfo, boolean synchronizedWithTransaction) {
|
EntityManager rawEntityManager, EntityManagerFactoryInfo emfInfo, boolean synchronizedWithTransaction) {
|
||||||
@@ -156,6 +157,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||||||
* @return a container-managed EntityManager that expects container-driven lifecycle
|
* @return a container-managed EntityManager that expects container-driven lifecycle
|
||||||
* management but may opt out of automatic transaction synchronization
|
* management but may opt out of automatic transaction synchronization
|
||||||
* @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map)
|
* @see javax.persistence.EntityManagerFactory#createEntityManager(java.util.Map)
|
||||||
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public static EntityManager createContainerManagedEntityManager(
|
public static EntityManager createContainerManagedEntityManager(
|
||||||
EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction) {
|
EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,19 +26,15 @@ import org.springframework.transaction.TransactionDefinition;
|
|||||||
import org.springframework.transaction.TransactionException;
|
import org.springframework.transaction.TransactionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SPI strategy that encapsulates certain functionality that standard JPA 2.0
|
* SPI strategy that encapsulates certain functionality that standard JPA 2.0 does
|
||||||
* does not offer, such as access to the underlying JDBC Connection. This
|
* not offer, such as access to the underlying JDBC Connection. This strategy is
|
||||||
* strategy is mainly intended for standalone usage of a JPA provider; most
|
* mainly intended for standalone usage of a JPA provider; most of its functionality
|
||||||
* of its functionality is not relevant when running with JTA transactions.
|
* is not relevant when running with JTA transactions.
|
||||||
*
|
*
|
||||||
* <p>Also allows for the provision of value-added methods for portable yet
|
* <p>In general, it is recommended to derive from {@link DefaultJpaDialect} instead
|
||||||
* more capable EntityManager and EntityManagerFactory subinterfaces offered
|
* of implementing this interface directly. This allows for inheriting common behavior
|
||||||
* by Spring.
|
* (present and future) from DefaultJpaDialect, only overriding specific hooks to
|
||||||
*
|
* plug in concrete vendor-specific behavior.
|
||||||
* <p>In general, it is recommended to derive from DefaultJpaDialect instead of
|
|
||||||
* implementing this interface directly. This allows for inheriting common
|
|
||||||
* behavior (present and future) from DefaultJpaDialect, only overriding
|
|
||||||
* specific hooks to plug in concrete vendor-specific behavior.
|
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
@@ -141,9 +137,8 @@ public interface JpaDialect extends PersistenceExceptionTranslator {
|
|||||||
* an implementation should use a special handle that references that other object.
|
* an implementation should use a special handle that references that other object.
|
||||||
* @param entityManager the current JPA EntityManager
|
* @param entityManager the current JPA EntityManager
|
||||||
* @param readOnly whether the Connection is only needed for read-only purposes
|
* @param readOnly whether the Connection is only needed for read-only purposes
|
||||||
* @return a handle for the JDBC Connection, to be passed into
|
* @return a handle for the Connection, to be passed into {@code releaseJdbcConnection},
|
||||||
* {@code releaseJdbcConnection}, or {@code null}
|
* or {@code null} if no JDBC Connection can be retrieved
|
||||||
* if no JDBC Connection can be retrieved
|
|
||||||
* @throws javax.persistence.PersistenceException if thrown by JPA methods
|
* @throws javax.persistence.PersistenceException if thrown by JPA methods
|
||||||
* @throws java.sql.SQLException if thrown by JDBC methods
|
* @throws java.sql.SQLException if thrown by JDBC methods
|
||||||
* @see #releaseJdbcConnection
|
* @see #releaseJdbcConnection
|
||||||
|
|||||||
+3
-1
@@ -68,7 +68,9 @@ import org.springframework.util.ClassUtils;
|
|||||||
* metadata as assembled by this FactoryBean.
|
* metadata as assembled by this FactoryBean.
|
||||||
*
|
*
|
||||||
* <p><b>NOTE: Spring's JPA support requires JPA 2.0 or higher, as of Spring 4.0.</b>
|
* <p><b>NOTE: Spring's JPA support requires JPA 2.0 or higher, as of Spring 4.0.</b>
|
||||||
* Spring's persistence unit bootstrapping automatically detects JPA 2.1 at runtime.
|
* JPA 1.0 based applications are still supported; however, a JPA 2.0/2.1 compliant
|
||||||
|
* persistence provider is needed at runtime. Spring's persistence unit bootstrapping
|
||||||
|
* automatically detects JPA 2.0 vs 2.1 through checking the JPA API on the classpath.
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
|
|||||||
+3
-1
@@ -41,7 +41,7 @@ import javax.persistence.spi.PersistenceProvider;
|
|||||||
* <p>This EntityManagerFactory bootstrap is appropriate for standalone applications
|
* <p>This EntityManagerFactory bootstrap is appropriate for standalone applications
|
||||||
* which solely use JPA for data access. If you want to set up your persistence
|
* which solely use JPA for data access. If you want to set up your persistence
|
||||||
* provider for an external DataSource and/or for global transactions which span
|
* provider for an external DataSource and/or for global transactions which span
|
||||||
* multiple resources, you will need to either deploy it into a full Java EE 5
|
* multiple resources, you will need to either deploy it into a full Java EE
|
||||||
* application server and access the deployed EntityManagerFactory via JNDI,
|
* application server and access the deployed EntityManagerFactory via JNDI,
|
||||||
* or use Spring's {@link LocalContainerEntityManagerFactoryBean} with appropriate
|
* or use Spring's {@link LocalContainerEntityManagerFactoryBean} with appropriate
|
||||||
* configuration for local setup according to JPA's container contract.
|
* configuration for local setup according to JPA's container contract.
|
||||||
@@ -53,6 +53,8 @@ import javax.persistence.spi.PersistenceProvider;
|
|||||||
* {@link LocalContainerEntityManagerFactoryBean} instead.
|
* {@link LocalContainerEntityManagerFactoryBean} instead.
|
||||||
*
|
*
|
||||||
* <p><b>NOTE: Spring's JPA support requires JPA 2.0 or higher, as of Spring 4.0.</b>
|
* <p><b>NOTE: Spring's JPA support requires JPA 2.0 or higher, as of Spring 4.0.</b>
|
||||||
|
* JPA 1.0 based applications are still supported; however, a JPA 2.0/2.1 compliant
|
||||||
|
* persistence provider is needed at runtime.
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ public abstract class SharedEntityManagerCreator {
|
|||||||
* @param synchronizedWithTransaction whether to automatically join ongoing
|
* @param synchronizedWithTransaction whether to automatically join ongoing
|
||||||
* transactions (according to the JPA 2.1 SynchronizationType rules)
|
* transactions (according to the JPA 2.1 SynchronizationType rules)
|
||||||
* @return a shareable transaction EntityManager proxy
|
* @return a shareable transaction EntityManager proxy
|
||||||
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public static EntityManager createSharedEntityManager(
|
public static EntityManager createSharedEntityManager(
|
||||||
EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction) {
|
EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction) {
|
||||||
@@ -145,6 +146,7 @@ public abstract class SharedEntityManagerCreator {
|
|||||||
* @param entityManagerInterfaces the interfaces to be implemented by the
|
* @param entityManagerInterfaces the interfaces to be implemented by the
|
||||||
* EntityManager. Allows the addition or specification of proprietary interfaces.
|
* EntityManager. Allows the addition or specification of proprietary interfaces.
|
||||||
* @return a shareable transactional EntityManager proxy
|
* @return a shareable transactional EntityManager proxy
|
||||||
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public static EntityManager createSharedEntityManager(EntityManagerFactory emf, Map<?, ?> properties,
|
public static EntityManager createSharedEntityManager(EntityManagerFactory emf, Map<?, ?> properties,
|
||||||
boolean synchronizedWithTransaction, Class<?>... entityManagerInterfaces) {
|
boolean synchronizedWithTransaction, Class<?>... entityManagerInterfaces) {
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,7 +30,7 @@ import org.springframework.util.Assert;
|
|||||||
* {@link FactoryBean} that exposes a shared JPA {@link javax.persistence.EntityManager}
|
* {@link FactoryBean} that exposes a shared JPA {@link javax.persistence.EntityManager}
|
||||||
* reference for a given EntityManagerFactory. Typically used for an EntityManagerFactory
|
* reference for a given EntityManagerFactory. Typically used for an EntityManagerFactory
|
||||||
* created by {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean},
|
* created by {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean},
|
||||||
* as direct alternative to a JNDI lookup for a Java EE 5 server's EntityManager reference.
|
* as direct alternative to a JNDI lookup for a Java EE server's EntityManager reference.
|
||||||
*
|
*
|
||||||
* <p>The shared EntityManager will behave just like an EntityManager fetched from an
|
* <p>The shared EntityManager will behave just like an EntityManager fetched from an
|
||||||
* application server's JNDI environment, as defined by the JPA specification.
|
* application server's JNDI environment, as defined by the JPA specification.
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ import static org.mockito.BDDMockito.*;
|
|||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @since 05.03.2005
|
* @since 05.03.2005
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })
|
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
|
||||||
public class HibernateTransactionManagerTests {
|
public class HibernateTransactionManagerTests {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
+2
-3
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -123,8 +123,7 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests
|
|||||||
newTony.getDriversLicense().getSerialNumber();
|
newTony.getDriversLicense().getSerialNumber();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
deleteFromTables(new String[] { "person", "drivers_license" });
|
deleteFromTables("person", "drivers_license");
|
||||||
//setComplete();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -87,9 +87,11 @@ public abstract class AbstractEntityManagerFactoryIntegrationTests extends Abstr
|
|||||||
protected int countRowsInTable(EntityManager em, String tableName) {
|
protected int countRowsInTable(EntityManager em, String tableName) {
|
||||||
Query query = em.createNativeQuery("SELECT COUNT(0) FROM " + tableName);
|
Query query = em.createNativeQuery("SELECT COUNT(0) FROM " + tableName);
|
||||||
return ((Number) query.getSingleResult()).intValue();
|
return ((Number) query.getSingleResult()).intValue();
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum Provider {
|
public enum Provider {
|
||||||
|
|
||||||
ECLIPSELINK, HIBERNATE, OPENJPA
|
ECLIPSELINK, HIBERNATE, OPENJPA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-9
@@ -121,15 +121,13 @@ public class ApplicationManagedEntityManagerIntegrationTests extends AbstractEnt
|
|||||||
doInstantiateAndSave(em);
|
doInstantiateAndSave(em);
|
||||||
setComplete();
|
setComplete();
|
||||||
endTransaction(); // Should rollback
|
endTransaction(); // Should rollback
|
||||||
assertEquals("Tx must have committed back",
|
assertEquals("Tx must have committed back", 1, countRowsInTable(em, "person"));
|
||||||
1, countRowsInTable(em, "person"));
|
|
||||||
|
|
||||||
// Now clean up the database
|
// Now clean up the database
|
||||||
startNewTransaction();
|
startNewTransaction();
|
||||||
em.joinTransaction();
|
em.joinTransaction();
|
||||||
deleteAllPeopleUsingEntityManager(em);
|
deleteAllPeopleUsingEntityManager(em);
|
||||||
assertEquals("People have been killed",
|
assertEquals("People have been killed", 0, countRowsInTable(em, "person"));
|
||||||
0, countRowsInTable(em, "person"));
|
|
||||||
setComplete();
|
setComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,8 +140,7 @@ public class ApplicationManagedEntityManagerIntegrationTests extends AbstractEnt
|
|||||||
em.joinTransaction();
|
em.joinTransaction();
|
||||||
doInstantiateAndSave(em);
|
doInstantiateAndSave(em);
|
||||||
endTransaction(); // Should rollback
|
endTransaction(); // Should rollback
|
||||||
assertEquals("Tx must have been rolled back",
|
assertEquals("Tx must have been rolled back", 0, countRowsInTable(em, "person"));
|
||||||
0, countRowsInTable(em, "person"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCommitOccurs() {
|
public void testCommitOccurs() {
|
||||||
@@ -153,11 +150,10 @@ public class ApplicationManagedEntityManagerIntegrationTests extends AbstractEnt
|
|||||||
|
|
||||||
setComplete();
|
setComplete();
|
||||||
endTransaction(); // Should rollback
|
endTransaction(); // Should rollback
|
||||||
assertEquals("Tx must have committed back",
|
assertEquals("Tx must have committed back", 1, countRowsInTable(em, "person"));
|
||||||
1, countRowsInTable(em, "person"));
|
|
||||||
|
|
||||||
// Now clean up the database
|
// Now clean up the database
|
||||||
deleteFromTables(new String[] { "person" });
|
deleteFromTables("person");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -104,8 +104,7 @@ public class ContainerManagedEntityManagerIntegrationTests extends AbstractEntit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void doInstantiateAndSave(EntityManager em) {
|
public void doInstantiateAndSave(EntityManager em) {
|
||||||
assertEquals("Should be no people from previous transactions",
|
assertEquals("Should be no people from previous transactions", 0, countRowsInTable(em, "person"));
|
||||||
0, countRowsInTable(em, "person"));
|
|
||||||
Person p = new Person();
|
Person p = new Person();
|
||||||
|
|
||||||
p.setFirstName("Tony");
|
p.setFirstName("Tony");
|
||||||
@@ -131,19 +130,17 @@ public class ContainerManagedEntityManagerIntegrationTests extends AbstractEntit
|
|||||||
doInstantiateAndSave(em);
|
doInstantiateAndSave(em);
|
||||||
setComplete();
|
setComplete();
|
||||||
endTransaction(); // Should rollback
|
endTransaction(); // Should rollback
|
||||||
assertEquals("Tx must have committed back",
|
assertEquals("Tx must have committed back", 1, countRowsInTable(em, "person"));
|
||||||
1, countRowsInTable(em, "person"));
|
|
||||||
|
|
||||||
// Now clean up the database
|
// Now clean up the database
|
||||||
deleteFromTables(new String[] { "person" });
|
deleteFromTables("person");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRollbackOccurs() {
|
public void testRollbackOccurs() {
|
||||||
EntityManager em = createContainerManagedEntityManager();
|
EntityManager em = createContainerManagedEntityManager();
|
||||||
doInstantiateAndSave(em);
|
doInstantiateAndSave(em);
|
||||||
endTransaction(); // Should rollback
|
endTransaction(); // Should rollback
|
||||||
assertEquals("Tx must have been rolled back",
|
assertEquals("Tx must have been rolled back", 0, countRowsInTable(em, "person"));
|
||||||
0, countRowsInTable(em, "person"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCommitOccurs() {
|
public void testCommitOccurs() {
|
||||||
@@ -151,11 +148,10 @@ public class ContainerManagedEntityManagerIntegrationTests extends AbstractEntit
|
|||||||
doInstantiateAndSave(em);
|
doInstantiateAndSave(em);
|
||||||
setComplete();
|
setComplete();
|
||||||
endTransaction(); // Should rollback
|
endTransaction(); // Should rollback
|
||||||
assertEquals("Tx must have committed back",
|
assertEquals("Tx must have committed back", 1, countRowsInTable(em, "person"));
|
||||||
1, countRowsInTable(em, "person"));
|
|
||||||
|
|
||||||
// Now clean up the database
|
// Now clean up the database
|
||||||
deleteFromTables(new String[] { "person" });
|
deleteFromTables("person");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-12
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -50,13 +50,13 @@ import static org.mockito.BDDMockito.*;
|
|||||||
*/
|
*/
|
||||||
public class JpaTransactionManagerTests {
|
public class JpaTransactionManagerTests {
|
||||||
|
|
||||||
|
private EntityManagerFactory factory;
|
||||||
|
|
||||||
private EntityManager manager;
|
private EntityManager manager;
|
||||||
|
|
||||||
private EntityTransaction tx;
|
private EntityTransaction tx;
|
||||||
|
|
||||||
private EntityManagerFactory factory;
|
private JpaTransactionManager tm;
|
||||||
|
|
||||||
private JpaTransactionManager transactionManager;
|
|
||||||
|
|
||||||
private TransactionTemplate tt;
|
private TransactionTemplate tt;
|
||||||
|
|
||||||
@@ -67,8 +67,8 @@ public class JpaTransactionManagerTests {
|
|||||||
manager = mock(EntityManager.class);
|
manager = mock(EntityManager.class);
|
||||||
tx = mock(EntityTransaction.class);
|
tx = mock(EntityTransaction.class);
|
||||||
|
|
||||||
transactionManager = new JpaTransactionManager(factory);
|
tm = new JpaTransactionManager(factory);
|
||||||
tt = new TransactionTemplate(transactionManager);
|
tt = new TransactionTemplate(tm);
|
||||||
|
|
||||||
given(factory.createEntityManager()).willReturn(manager);
|
given(factory.createEntityManager()).willReturn(manager);
|
||||||
given(manager.getTransaction()).willReturn(tx);
|
given(manager.getTransaction()).willReturn(tx);
|
||||||
@@ -83,6 +83,7 @@ public class JpaTransactionManagerTests {
|
|||||||
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
assertFalse(TransactionSynchronizationManager.isActualTransactionActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionCommit() {
|
public void testTransactionCommit() {
|
||||||
given(manager.getTransaction()).willReturn(tx);
|
given(manager.getTransaction()).willReturn(tx);
|
||||||
@@ -456,7 +457,7 @@ public class JpaTransactionManagerTests {
|
|||||||
@Override
|
@Override
|
||||||
public Object doInTransaction(TransactionStatus status) {
|
public Object doInTransaction(TransactionStatus status) {
|
||||||
assertFalse(TransactionSynchronizationManager.hasResource(factory));
|
assertFalse(TransactionSynchronizationManager.hasResource(factory));
|
||||||
TransactionTemplate tt2 = new TransactionTemplate(transactionManager);
|
TransactionTemplate tt2 = new TransactionTemplate(tm);
|
||||||
tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||||
return tt2.execute(new TransactionCallback() {
|
return tt2.execute(new TransactionCallback() {
|
||||||
@Override
|
@Override
|
||||||
@@ -497,7 +498,7 @@ public class JpaTransactionManagerTests {
|
|||||||
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
EntityManagerFactoryUtils.getTransactionalEntityManager(factory);
|
||||||
|
|
||||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||||
TransactionTemplate tt2 = new TransactionTemplate(transactionManager);
|
TransactionTemplate tt2 = new TransactionTemplate(tm);
|
||||||
tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
tt2.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||||
return tt2.execute(new TransactionCallback() {
|
return tt2.execute(new TransactionCallback() {
|
||||||
@Override
|
@Override
|
||||||
@@ -660,7 +661,6 @@ public class JpaTransactionManagerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionRollbackWithPrebound() {
|
public void testTransactionRollbackWithPrebound() {
|
||||||
|
|
||||||
given(manager.getTransaction()).willReturn(tx);
|
given(manager.getTransaction()).willReturn(tx);
|
||||||
given(tx.isActive()).willReturn(true);
|
given(tx.isActive()).willReturn(true);
|
||||||
|
|
||||||
@@ -694,7 +694,6 @@ public class JpaTransactionManagerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionCommitWithPreboundAndPropagationSupports() {
|
public void testTransactionCommitWithPreboundAndPropagationSupports() {
|
||||||
|
|
||||||
final List<String> l = new ArrayList<String>();
|
final List<String> l = new ArrayList<String>();
|
||||||
l.add("test");
|
l.add("test");
|
||||||
|
|
||||||
@@ -730,7 +729,6 @@ public class JpaTransactionManagerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransactionRollbackWithPreboundAndPropagationSupports() {
|
public void testTransactionRollbackWithPreboundAndPropagationSupports() {
|
||||||
|
|
||||||
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
|
||||||
|
|
||||||
assertTrue(!TransactionSynchronizationManager.hasResource(factory));
|
assertTrue(!TransactionSynchronizationManager.hasResource(factory));
|
||||||
@@ -765,7 +763,7 @@ public class JpaTransactionManagerTests {
|
|||||||
@Test
|
@Test
|
||||||
public void testTransactionCommitWithDataSource() throws SQLException {
|
public void testTransactionCommitWithDataSource() throws SQLException {
|
||||||
DataSource ds = mock(DataSource.class);
|
DataSource ds = mock(DataSource.class);
|
||||||
transactionManager.setDataSource(ds);
|
tm.setDataSource(ds);
|
||||||
|
|
||||||
given(manager.getTransaction()).willReturn(tx);
|
given(manager.getTransaction()).willReturn(tx);
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -38,8 +38,7 @@ public class SharedEntityManagerCreatorTests {
|
|||||||
EntityManagerFactory emf = mock(EntityManagerFactory.class,
|
EntityManagerFactory emf = mock(EntityManagerFactory.class,
|
||||||
withSettings().extraInterfaces(EntityManagerFactoryInfo.class));
|
withSettings().extraInterfaces(EntityManagerFactoryInfo.class));
|
||||||
// EntityManagerFactoryInfo.getEntityManagerInterface returns null
|
// EntityManagerFactoryInfo.getEntityManagerInterface returns null
|
||||||
assertThat(SharedEntityManagerCreator.createSharedEntityManager(emf),
|
assertThat(SharedEntityManagerCreator.createSharedEntityManager(emf), is(notNullValue()));
|
||||||
is(notNullValue()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = TransactionRequiredException.class)
|
@Test(expected = TransactionRequiredException.class)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:context="http://www.springframework.org/schema/context"
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
|
||||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
||||||
|
|
||||||
<context:annotation-config/>
|
<context:annotation-config/>
|
||||||
@@ -11,13 +11,13 @@
|
|||||||
|
|
||||||
<bean class="org.springframework.orm.jpa.support.PersistenceInjectionTests$DefaultPublicPersistenceContextSetter"/>
|
<bean class="org.springframework.orm.jpa.support.PersistenceInjectionTests$DefaultPublicPersistenceContextSetter"/>
|
||||||
|
|
||||||
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">
|
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">
|
||||||
<property name="proxyTargetClass" value="true"/>
|
<property name="proxyTargetClass" value="true"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true">
|
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true">
|
||||||
<property name="targetObject" ref="dao"/>
|
<property name="targetObject" ref="dao"/>
|
||||||
<property name="targetMethod" value="toString"/>
|
<property name="targetMethod" value="toString"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
-5
@@ -51,11 +51,6 @@ public class PersistenceInjectionIntegrationTests extends AbstractEntityManagerF
|
|||||||
assertNotNull("Default PersistenceContext Setter was injected", injectedEm);
|
assertNotNull("Default PersistenceContext Setter was injected", injectedEm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInjectedEntityManagerImplmentsPortableEntityManagerPlus() {
|
|
||||||
EntityManager injectedEm = defaultSetterInjected.getEntityManager();
|
|
||||||
assertNotNull("Default PersistenceContext Setter was injected", injectedEm);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSetterInjectionOfNamedPersistenceContext() {
|
public void testSetterInjectionOfNamedPersistenceContext() {
|
||||||
assertNotNull("Named PersistenceContext Setter was injected", namedSetterInjected.getEntityManagerFactory());
|
assertNotNull("Named PersistenceContext Setter was injected", namedSetterInjected.getEntityManagerFactory());
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-23
@@ -330,8 +330,9 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
assertSame(mockEmf2, bean2.emf);
|
assertSame(mockEmf2, bean2.emf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void ignoreTestPersistenceUnitsFromJndi() {
|
public void testPersistenceUnitsFromJndi() {
|
||||||
EntityManager mockEm = mock(EntityManager.class);
|
EntityManager mockEm = mock(EntityManager.class);
|
||||||
given(mockEmf.createEntityManager()).willReturn(mockEm);
|
given(mockEmf.createEntityManager()).willReturn(mockEm);
|
||||||
|
|
||||||
@@ -542,9 +543,9 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFieldOfWrongTypeAnnotatedWithPersistenceUnit() {
|
public void testFieldOfWrongTypeAnnotatedWithPersistenceUnit() {
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new PersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor();
|
||||||
try {
|
try {
|
||||||
babpp.postProcessPropertyValues(null, null, new FieldOfWrongTypeAnnotatedWithPersistenceUnit(), "bean");
|
pabpp.postProcessPropertyValues(null, null, new FieldOfWrongTypeAnnotatedWithPersistenceUnit(), "bean");
|
||||||
fail("Can't inject this field");
|
fail("Can't inject this field");
|
||||||
}
|
}
|
||||||
catch (IllegalStateException ex) {
|
catch (IllegalStateException ex) {
|
||||||
@@ -554,9 +555,9 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetterOfWrongTypeAnnotatedWithPersistenceUnit() {
|
public void testSetterOfWrongTypeAnnotatedWithPersistenceUnit() {
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new PersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor();
|
||||||
try {
|
try {
|
||||||
babpp.postProcessPropertyValues(null, null, new SetterOfWrongTypeAnnotatedWithPersistenceUnit(), "bean");
|
pabpp.postProcessPropertyValues(null, null, new SetterOfWrongTypeAnnotatedWithPersistenceUnit(), "bean");
|
||||||
fail("Can't inject this setter");
|
fail("Can't inject this setter");
|
||||||
}
|
}
|
||||||
catch (IllegalStateException ex) {
|
catch (IllegalStateException ex) {
|
||||||
@@ -566,9 +567,9 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetterWithNoArgs() {
|
public void testSetterWithNoArgs() {
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new PersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new PersistenceAnnotationBeanPostProcessor();
|
||||||
try {
|
try {
|
||||||
babpp.postProcessPropertyValues(null, null, new SetterWithNoArgs(), "bean");
|
pabpp.postProcessPropertyValues(null, null, new SetterWithNoArgs(), "bean");
|
||||||
fail("Can't inject this setter");
|
fail("Can't inject this setter");
|
||||||
}
|
}
|
||||||
catch (IllegalStateException ex) {
|
catch (IllegalStateException ex) {
|
||||||
@@ -576,28 +577,28 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
@Test
|
||||||
public void ignoreTestNoPropertiesPassedIn() {
|
public void testNoPropertiesPassedIn() {
|
||||||
EntityManager mockEm = mock(EntityManager.class);
|
EntityManager mockEm = mock(EntityManager.class);
|
||||||
given(mockEmf.createEntityManager()).willReturn(mockEm);
|
given(mockEmf.createEntityManager()).willReturn(mockEm);
|
||||||
|
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new MockPersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor();
|
||||||
DefaultPrivatePersistenceContextFieldExtended dppcf = new DefaultPrivatePersistenceContextFieldExtended();
|
DefaultPrivatePersistenceContextFieldExtended dppcf = new DefaultPrivatePersistenceContextFieldExtended();
|
||||||
babpp.postProcessAfterInstantiation(dppcf, "bean name does not matter");
|
pabpp.postProcessPropertyValues(null, null, dppcf, "bean");
|
||||||
assertNotNull(dppcf.em);
|
assertNotNull(dppcf.em);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore
|
@Test
|
||||||
public void ignoreTestPropertiesPassedIn() {
|
public void testPropertiesPassedIn() {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.put("foo", "bar");
|
props.put("foo", "bar");
|
||||||
EntityManager mockEm = mock(EntityManager.class);
|
EntityManager mockEm = mock(EntityManager.class);
|
||||||
given(mockEmf.createEntityManager(props)).willReturn(mockEm);
|
given(mockEmf.createEntityManager(props)).willReturn(mockEm);
|
||||||
|
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new MockPersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor();
|
||||||
DefaultPrivatePersistenceContextFieldExtendedWithProps dppcf =
|
DefaultPrivatePersistenceContextFieldExtendedWithProps dppcf =
|
||||||
new DefaultPrivatePersistenceContextFieldExtendedWithProps();
|
new DefaultPrivatePersistenceContextFieldExtendedWithProps();
|
||||||
babpp.postProcessAfterInstantiation(dppcf, "bean name does not matter");
|
pabpp.postProcessPropertyValues(null, null, dppcf, "bean");
|
||||||
assertNotNull(dppcf.em);
|
assertNotNull(dppcf.em);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,10 +611,10 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
given(em.getDelegate()).willReturn(new Object());
|
given(em.getDelegate()).willReturn(new Object());
|
||||||
given(em.isOpen()).willReturn(true);
|
given(em.isOpen()).willReturn(true);
|
||||||
|
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new MockPersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor();
|
||||||
DefaultPrivatePersistenceContextFieldWithProperties transactionalField =
|
DefaultPrivatePersistenceContextFieldWithProperties transactionalField =
|
||||||
new DefaultPrivatePersistenceContextFieldWithProperties();
|
new DefaultPrivatePersistenceContextFieldWithProperties();
|
||||||
babpp.postProcessPropertyValues(null, null, transactionalField, "bean");
|
pabpp.postProcessPropertyValues(null, null, transactionalField, "bean");
|
||||||
|
|
||||||
assertNotNull(transactionalField.em);
|
assertNotNull(transactionalField.em);
|
||||||
assertNotNull(transactionalField.em.getDelegate());
|
assertNotNull(transactionalField.em.getDelegate());
|
||||||
@@ -635,13 +636,13 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
given(em.getDelegate()).willReturn(new Object());
|
given(em.getDelegate()).willReturn(new Object());
|
||||||
given(em.isOpen()).willReturn(true);
|
given(em.isOpen()).willReturn(true);
|
||||||
|
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new MockPersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor();
|
||||||
DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties =
|
DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties =
|
||||||
new DefaultPrivatePersistenceContextFieldWithProperties();
|
new DefaultPrivatePersistenceContextFieldWithProperties();
|
||||||
DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField();
|
DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField();
|
||||||
|
|
||||||
babpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1");
|
pabpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1");
|
||||||
babpp.postProcessPropertyValues(null, null, transactionalField, "bean2");
|
pabpp.postProcessPropertyValues(null, null, transactionalField, "bean2");
|
||||||
|
|
||||||
assertNotNull(transactionalFieldWithProperties.em);
|
assertNotNull(transactionalFieldWithProperties.em);
|
||||||
assertNotNull(transactionalField.em);
|
assertNotNull(transactionalField.em);
|
||||||
@@ -668,13 +669,13 @@ public class PersistenceInjectionTests extends AbstractEntityManagerFactoryBeanT
|
|||||||
given(em.getDelegate()).willReturn(new Object(), 2);
|
given(em.getDelegate()).willReturn(new Object(), 2);
|
||||||
given(em.isOpen()).willReturn(true);
|
given(em.isOpen()).willReturn(true);
|
||||||
|
|
||||||
PersistenceAnnotationBeanPostProcessor babpp = new MockPersistenceAnnotationBeanPostProcessor();
|
PersistenceAnnotationBeanPostProcessor pabpp = new MockPersistenceAnnotationBeanPostProcessor();
|
||||||
DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties =
|
DefaultPrivatePersistenceContextFieldWithProperties transactionalFieldWithProperties =
|
||||||
new DefaultPrivatePersistenceContextFieldWithProperties();
|
new DefaultPrivatePersistenceContextFieldWithProperties();
|
||||||
DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField();
|
DefaultPrivatePersistenceContextField transactionalField = new DefaultPrivatePersistenceContextField();
|
||||||
|
|
||||||
babpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1");
|
pabpp.postProcessPropertyValues(null, null, transactionalFieldWithProperties, "bean1");
|
||||||
babpp.postProcessPropertyValues(null, null, transactionalField, "bean2");
|
pabpp.postProcessPropertyValues(null, null, transactionalField, "bean2");
|
||||||
|
|
||||||
assertNotNull(transactionalFieldWithProperties.em);
|
assertNotNull(transactionalFieldWithProperties.em);
|
||||||
assertNotNull(transactionalField.em);
|
assertNotNull(transactionalField.em);
|
||||||
|
|||||||
+5
-6
@@ -48,8 +48,7 @@ import org.springframework.test.jdbc.JdbcTestUtils;
|
|||||||
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests})
|
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests})
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public abstract class AbstractTransactionalDataSourceSpringContextTests
|
public abstract class AbstractTransactionalDataSourceSpringContextTests extends AbstractTransactionalSpringContextTests {
|
||||||
extends AbstractTransactionalSpringContextTests {
|
|
||||||
|
|
||||||
protected JdbcTemplate jdbcTemplate;
|
protected JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
@@ -105,11 +104,11 @@ public abstract class AbstractTransactionalDataSourceSpringContextTests
|
|||||||
* {@code setComplete()} impossible.
|
* {@code setComplete()} impossible.
|
||||||
* @see #setComplete
|
* @see #setComplete
|
||||||
*/
|
*/
|
||||||
protected void deleteFromTables(String[] names) {
|
protected void deleteFromTables(String... names) {
|
||||||
for (int i = 0; i < names.length; i++) {
|
for (String name : names) {
|
||||||
int rowCount = this.jdbcTemplate.update("DELETE FROM " + names[i]);
|
int rowCount = this.jdbcTemplate.update("DELETE FROM " + name);
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
logger.info("Deleted " + rowCount + " rows from table " + names[i]);
|
logger.info("Deleted " + rowCount + " rows from table " + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.zappedTables = true;
|
this.zappedTables = true;
|
||||||
|
|||||||
@@ -127,8 +127,7 @@ public abstract class Log4jWebConfigurer {
|
|||||||
|
|
||||||
// Leave a URL (e.g. "classpath:" or "file:") as-is.
|
// Leave a URL (e.g. "classpath:" or "file:") as-is.
|
||||||
if (!ResourceUtils.isUrl(location)) {
|
if (!ResourceUtils.isUrl(location)) {
|
||||||
// Consider a plain file path as relative to the web
|
// Consider a plain file path as relative to the web application root directory.
|
||||||
// application root directory.
|
|
||||||
location = WebUtils.getRealPath(servletContext, location);
|
location = WebUtils.getRealPath(servletContext, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user