В этой статье я расскажу, как подключиться к 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]