Статьи

Интеграционное тестирование для приложений Spring с пулами соединений JNDI

Мы все знаем, что нам нужно использовать пулы соединений, где бы мы ни подключались к базе данных. Все современные драйверы, использующие JDBC type 4, поддерживают его. В этой статье мы рассмотрим обзор пула подключений в весенних приложениях и способы работы с тем же контекстом в среде, не относящейся к JEE (например, тесты).

Большинство примеров подключения к базе данных весной выполняется с помощью DriverManagerDataSource. Если вы не прочитали документацию должным образом, вы пропустите очень важный момент.

ПРИМЕЧАНИЕ. Этот класс не является фактическим пулом соединений; на самом деле он не объединяет соединения. Он просто служит простой заменой полноценного пула соединений, реализуя тот же стандартный интерфейс, но создавая новые соединения при каждом вызове.

Полезно для тестовых или автономных сред вне контейнера J2EE, либо в качестве bean-компонента DataSource в соответствующем ApplicationContext, либо в сочетании с простой средой JNDI. Предполагая, что вызовы Connection.close () пула просто закроют соединение, поэтому любой персистентный код с поддержкой DataSource должен работать.

Да, по умолчанию приложения Spring не используют пул соединений. Есть два способа реализовать пул соединений. В зависимости от того, кто управляет бассейном. Если вы работаете в среде JEE, то для этого предпочтительно использовать контейнер. В не-JEE-настройке есть библиотеки, которые помогут приложению управлять пулами соединений. Давайте обсудим их немного подробнее ниже.

1. Сервер (контейнер) управляемый пул соединений (с использованием JNDI)

жулик бассейн

Когда приложение подключается к серверу базы данных, установление фактического физического соединения занимает гораздо больше, чем выполнение сценариев. Пулы соединений — это метод, который был впервые применен поставщиками баз данных, чтобы позволить нескольким клиентам совместно использовать кэшированный набор объектов соединений, которые обеспечивают доступ к ресурсу базы данных. Статья JavaWorld дает хороший обзор об этом.

В контейнере J2EE рекомендуется использовать источник данных JNDI, предоставленный контейнером. Такой DataSource может быть представлен как bean-компонент DataSource в Spring ApplicationContext через JndiObjectFactoryBean , для плавного переключения на и с локального bean-компонента DataSource, такого как этот класс.

Приведенные ниже статьи помогли мне настроить источник данных в JBoss AS.

  1. DebaJava Post
  2. Руководство по установке JBoss
  3. JBoss Wiki

Следующим шагом является использование этих соединений, созданных сервером из приложения. Как упомянуто в документации, вы можете использовать для этого JndiObjectFactoryBean . Это так же просто, как показано ниже

1
2
3
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:/my-ds"/>
</bean>

Если вы хотите написать какие-либо тесты с использованием пружин «SpringJUnit4ClassRunner», он не сможет загрузить контекст, потому что ресурс JNDI будет недоступен.

Для тестов вы можете либо установить фиктивную среду JNDI через SpringN SimpleNamingContextBuilder, либо переключить определение компонента на локальный источник данных (который проще и поэтому рекомендуется).

Поскольку я искал хорошие решения этой проблемы (я не хотел отдельного контекста для тестов), этот SO-ответ мне помог. Он как бы использует различные советы, приведенные в Javadoc, для хорошего эффекта. Проблема с вышеупомянутым решением — повторение кода для создания соединений JNDI. Я решил это с помощью настроенного раннера SpringWithJNDIRunner . Этот класс добавляет возможности JNDI в SpringJUnit4ClassRunner. Он считывает источник данных из файла «test-datasource.xml» в пути к классам и связывает его с ресурсом JNDI с именем «java: / my-ds». После выполнения этого кода ресурс JNDI становится доступным для использования контейнером пружины.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import javax.naming.NamingException;
 
import org.junit.runners.model.InitializationError;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
/**
 * This class adds the JNDI capabilities to the SpringJUnit4ClassRunner.
 * @author mkadicha
 *
 */
public class SpringWithJNDIRunner extends SpringJUnit4ClassRunner {
 
    public static boolean isJNDIactive;
 
    /**
     * JNDI is activated with this constructor.
     *
     * @param klass
     * @throws InitializationError
     * @throws NamingException
     * @throws IllegalStateException
     */
    public SpringWithJNDIRunner(Class<?> klass) throws InitializationError,
            IllegalStateException, NamingException {
        super(klass);
         
        synchronized (SpringWithJNDIRunner.class) {
            if (!isJNDIactive) {
 
                ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                        "test-datasource.xml");
 
                SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
                builder.bind("java:/my-ds",
                        applicationContext.getBean("dataSource"));
                builder.activate();
 
                isJNDIactive = true;
            }
        }
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
 
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="" />
        <property name="url" value="" />
        <property name="username" value="" />
        <property name="password" value="" />
    </bean>
     
</beans>

Чтобы использовать этот бегун, вам просто нужно использовать аннотацию @RunWith (SpringWithJNDIRunner.class) в вашем тесте. Этот класс расширяет SpringJUnit4ClassRunner, поскольку в аннотации @RunWith может быть только один класс. JNDI создается только один раз за цикл тестирования. Этот класс обеспечивает чистое решение проблемы.

2. Пул управляемых приложением соединений

Если вам нужен «реальный» пул соединений вне J2EE-контейнера, рассмотрите Japarta Commons DBCP или C3P0 от Apache. BasicDataSource от Commons DBCP и ComboPooledDataSource для C3P0 являются компонентами полного пула соединений, поддерживающими те же базовые свойства, что и этот класс, а также определенные параметры (такие как минимальный / максимальный размер пула и т. Д.).

Ниже руководства пользователя могут помочь вам настроить это.

  1. Весенние Документы
  2. C3P0 Руководство пользователя
  3. DBCP Руководство пользователя

В следующих статьях рассказывается об общих рекомендациях и рекомендациях по настройке пулов соединений.

  1. ТАК вопрос по пулам Spring JDBC Connection
  2. Максимальный размер пула соединений в MS SQL Server 2008
  3. Как определить максимальное количество соединений
  4. Отслеживание количества активных подключений в SQL Server 2008