Статьи

Как подключиться к MongoDB из приложения Java EE без сохранения состояния

В этой статье я расскажу, как подключиться к MongoDB из приложения Java EE без сохранения состояния, чтобы воспользоваться встроенным пулом подключений к базе данных, предлагаемым драйвером MongoDB Java Driver. Это может иметь место при разработке REST API, который выполняет операции с MongoDB.

Получите драйвер Java MongoDb

Для подключения из Java к MongoDB вы можете использовать драйвер Java MongoDB . Если вы создаете свое приложение с помощью Maven, вы можете добавить зависимость в файл pom.xml:

<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.12.3</version>
</dependency>

Драйвер предоставляет клиенту MongoDB (com.mongodb.MongoClient) внутренний пул. Класс MongoClient разработан для обеспечения многопоточности и совместного использования между потоками. Для большинства приложений у вас должно быть одно хранилище MongoClient для всей JVM. По этой причине вам не нужно создавать новое хранилище MongoClient с каждым запросом в приложении Java EE без сохранения состояния.

Реализация @Singleton EJB

Простое решение — использовать @Singleton EJB для хранения MongoClient:

package org.codingpedia.demo.mongoconnection;

import java.net.UnknownHostException;

import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;

import com.mongodb.MongoClient;

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class MongoClientProvider {

private MongoClient mongoClient = null;

@Lock(LockType.READ)
public MongoClient getMongoClient(){
return mongoClient;
}

@PostConstruct
public void init() {
String mongoIpAddress = "x.x.x.x";
Integer mongoPort = 11000;
try {
mongoClient = new MongoClient(mongoIpAddress, mongoPort);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

Примечание:

  • @Singleton — вероятно, самая важная строка кода в этом классе. Эта аннотация указывает, что в приложении будет ровно один синглтон этого типа компонента. Этот бин может быть вызван одновременно несколькими потоками. Он также поставляется с  @PostConstruct аннотацией. Эта аннотация используется для метода, который необходимо выполнить после внедрения зависимости для выполнения любой инициализации — в нашем случае это инициализация MongoClient
  • @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) объявляет тип управления параллелизмом одноплодного сессионного компонента. По умолчанию установлено, что  Container, я использую его здесь только для выделения его существования. Другая опция  ConcurrencyManagementType.BEAN указывает, что разработчик компонента отвечает за управление одновременным доступом к экземпляру компонента.
  • @Lock(LockType.READ) определяет параллелизм типа блокировки для одноэлементной фасоли с управляемым контейнером параллелизмом. Когда установлено значение  LockType.READ, он применяет метод для разрешения полного одновременного доступа к нему (при условии, что блокировки записи не удерживаются). Это позволяет нескольким потокам обращаться к одному экземпляру MongoClient и использовать преимущества внутреннего пула соединений с базой данных. Это ОЧЕНЬ ВАЖНО, потому что другой более консервативный вариант  @Lock(LockType.WRITE)— DEFAULT и обеспечивает эксклюзивный доступ к экземпляру компонента. Это должно замедлить метод в среде с высокой степенью параллелизма …

Используйте @Singleton EJB

Теперь, когда у вас есть MongoClient, «сохраненный» в приложении, вы можете внедрить MongoClientProvider для доступа к MongoDB (например, для получения имен коллекции):

package org.codingpedia.demo.mongoconnection;

import java.util.Set;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.util.JSON;

@Stateless
public class TestMongoClientProvider {

@EJB
MongoClientProvider mongoClientProvider;

public Set<String> getCollectionNames(){

MongoClient mongoClient = mongoClientProvider.getMongoClient();

DB db = mongoClient.getDB("myMongoDB");
Set<String> colls = db.getCollectionNames();

for (String s : colls) {
    System.out.println(s);
}

return colls;
}

}

Примечание. Объект db будет подключаться к серверу MongoDB для указанной базы данных. С его помощью вы можете выполнять дальнейшие операции. Я рекомендую вам прочитать « Начало работы с драйвером Java», чтобы узнать больше об этом…

Знать

Один аспект, на который нужно обратить внимание:

«Для каждого запроса к БД (поиск, вставка и т. Д.) Поток Java получит соединение из пула, выполнит операцию и освободит соединение. Это означает, что используемое соединение (розетка) может каждый раз отличаться.

Кроме того, в случае набора реплик с включенной опцией slaveOk операции чтения будут равномерно распределены по всем ведомым. Это означает, что в одном и том же потоке запись, за которой следует чтение, может быть отправлена ​​на разные серверы (главный, а затем подчиненный). В свою очередь, операция чтения может не видеть только что записанные данные, поскольку репликация является асинхронной. Если вы хотите обеспечить полную согласованность в «сеансе» (может быть, запрос http), вы бы хотели, чтобы драйвер использовал тот же сокет, чего можно добиться, используя «согласованный запрос». Вызовите requestStart () перед вашими операциями и requestDone (), чтобы освободить соединение обратно в пул:

<em>DB db...;
db.requestStart();
try {
   db.requestEnsureConnection();

   code....
} finally {
   db.requestDone();
}</em>

DB и DBCollection полностью поточнобезопасны. На самом деле они кэшируются, поэтому вы получаете один и тот же экземпляр, несмотря ни на что ». [3]

Ресурсы

  1. Java MongoDB Драйвер
  2. Начало работы с драйвером Java
  3. Параллелизм драйвера Java
  4. GitHub — примеры mongodb / mongo-java-driver