当前位置: 首页 > 知识库问答 >
问题:

以面向对象的方式管理Java中的Mongodb连接

葛昱
2023-03-14

如何使用多个类正确管理mongo连接?

例如,我有4个类管理4个集合。

收藏1。班级集合2。班级等等。。

我要做的是在每个类中创建一个connect and close方法,这会减慢应用程序中某些事务的连接

除了创建每个类的对象并分别连接每个类之外,将应用程序连接到db并开始使用所有类实例的最佳方式是什么?

共有2个答案

越狐若
2023-03-14

您说对了,每个类(表示MongoDB集合)不应该管理自己与数据库的连接。相反,您应该将数据库连接传递到类中——通常是在构造函数中。类似于这样:

class Animal {
    private String species;
    private String name;
    private int age;

    public Animal(DBObject dbObject) { ... }
}

class AnimalCollection {
    private final DBCollection collection;        

    public AnimalCollection(Database database) {
        collection = database.getCollection("animals");
    }

    public List<Animal> getAll() {
        List<Animal> animals 
        try (DBCursor cursor = collection.find(query)) {
            while (cursor.hasNext()) {
                animals.add(new Animal(cursor.next());
            }
        }
        return animals;
    }
}

创建所有集合的代码应该获得MongoClient,连接到DB,并在退出时管理关闭连接。这样,您就可以管理一个连接。

因此,管理集合的类可能看起来像:

class CollectionManager implements AutoCloseable {
    private final Database database;
    private final AnimalCollection animals;

    public CollectionManager(MongoClient client) {
        database = client.getDB("Zoo");
        animals = new AnimalCollection(database);
    }

    @Override
    public void close() {
        database.close();
    }
}

让此类扩展AutoCloseable的原因是退出try with resources块时会自动调用close。这将使你的代码更容易阅读,更安全。

这种方法还有一个很大的优点。您可以通过在构造函数中传递一个模拟的数据库来单元测试您的类,并测试响应各种数据库输出的行为,而不需要一个包含任何数据的实际数据库。

经俊茂
2023-03-14

在应用程序中,使用连接池的单个MongoClient对象具有所需数量的连接,在这种情况下可以工作。连接池的默认值为100,可以根据需要修改(或配置)。

mongo客户端对象可以在应用程序开始时创建,并且只有在应用程序关闭时才会关闭。这将节省与在每个集合访问类中创建与mongo客户端对象的连接相关的资源。

相同的mongo客户端对象可以在整个应用程序中使用。应用程序中需要连接到MongoDB数据库服务器的任何其他对象都可以访问单例类(维护mongo客户端对象的一个实例)。

在软件工程中,连接池是维护的数据库连接的缓存,以便将来需要向数据库发出请求时可以重复使用这些连接。连接池用于增强在数据库上执行命令的性能。为每个用户打开和维护数据库连接,特别是向动态数据库驱动的网站应用程序发出的请求,成本很高,而且浪费资源。在连池中,创建连接后,它被放置在池中,并再次使用,这样就不必建立新的连接。如果所有连接都在使用,则会建立新的连接并添加到池中。连接池还减少了用户建立到数据库的连接所必须等待的时间。

示例代码:

/*
 * Manages the MongoClient object and its settings like host, port, connection pool, etc.
 */
public class DBAccess {

  private static MongoClient mongoClient;
  private static DBAccess dbAccess;

  // MongoClient with default settings
  // NOTE: the code will have only one of the constructors
  //private DBAccess() {
  //    final String connectionString = "mongodb://localhost:27017";
  //    this.mongoClient = MongoClients.create(connectionString);
  //}

  // MongoClient with custom settings.
  // Private constructor, so that the class can be instantiated outside this class.
  // NOTE: the code will have only one of the constructors
  private DBAccess() {

      MongoClientSettings settings =
          MongoClientSettings.builder()
              .applyToConnectionPoolSettings(builder ->
                   builder.maxSize(40).minSize(10))
             .applyToClusterSettings(builder ->
                   builder.hosts(Arrays.asList(new ServerAddress("localhost", 27017))))
            .build();

      mongoClient = MongoClients.create(settings);
  }

  public static MongoClient getConnection() {

      if (dbAccess == null) {
           dbAccess = new DBAccess();   
      }

      return mongoClient;
  }

  public static void closeDatabase() {
      mongoClient.close();
  }
}

/*
 * Class manages a collection.
 */
public class CollectionOneAccess {

  public static String COLLECTION_ONE = "collection_one";
  private MongoCollection<Document> collection;

  public CollectionOneAccess(MongoDatabase db) {    
      collection = db.getCollection(COLLECTION_ONE);
  }

  public void printOneDocument() {
      Document myDoc = collection.find().first();
      System.out.println(myDoc.toJson());
  }

  // other CRUD operations ...

}


// Usage of DBAcess and CollectionOneAccess classes:

private static final String APP_DATABASE = "abc_db";

public static void main(String [] args) {
    MongoDatabase database = DBAccess.getConnection().getDatabase(APP_DATABASE);
    CollectionOneAccess one = new CollectionOneAccess(database);
    one.printOneDocument();
    // ...
}

Mongo客户端

MongoClient对象用于连接到MongoDB服务器,使用getDatebase()方法访问数据库,并使用集合。

com.mongodb.客户MongoClient界面:

MongoDB集群的客户端表示。实例可以表示独立的MongoDB实例、副本集或分片集群。此类的实例负责维护集群的最新状态,并可能缓存与此相关的资源,包括用于监视的后台线程和连接池。

来自MongoDB Java文档:

MongoClient实例表示到数据库的连接池;即使使用多个线程,也只需要类MongoClient的一个实例。

重要提示:通常,对于给定的MongoDB部署(例如独立、副本集或分片集群),您只创建一个MongoClient实例,并在应用程序中使用它。但是,如果您创建了多个实例:

  • 所有资源使用限制(如最大连接数等)适用于每个MongoClient实例
  • 要处理实例,请调用MongoClient。关闭()以清理资源

下面的代码使用默认设置创建一个MongoDB客户端连接对象,如主机(“localhost”)和端口(27017)、连接池等,并连接到MongoDB实例并访问testDB数据库。

MongoClient mongoClient = MongoClients.create();
MongoDatabase database = mongoClient.getDatabase("testDB");

Mongo客户端设置:

您可以使用MongoClientSettings显式指定其他设置,以控制MongoClient的行为。

MongoClient mongoClient = MongoClients.create(MongoClientSettings settings)

ConnectionPoolSettings对象指定与MongoDB服务器的连接池相关的所有设置。应用程序在创建客户端对象时创建此连接池<代码>连接池设置。Builder是用于连接池设置的生成器,具有指定连接池属性的方法。例如,maxSize​(int maxSize):允许的最大连接数(默认值为100)。其他方法包括,minSizemaxConnectionIdleTime,等等。

使用连接池设置实例化MongoClient的代码:

MongoClientSettings settings = MongoClientSettings.builder()
                                   .applyToConnectionPoolSettings(builder -> 
                                       builder.maxSize(20))
                                   .build();
MongoClient mongoClient = MongoClients.create(settings);
// ...
// Verify the connection pool settings 
System.out.println("Pool size: " + 
    settings.getConnectionPoolSettings().getMaxSize());

 类似资料:
  • 我有一个C(而不是C)库,它一致地使用函数的第一个参数作为上下文对象(让我们调用类型),我想使用SWIG生成C#wrappers来保持这种调用风格(也就是说,不要把函数或多或少地孤立起来,而是把它们包装成某个类中的方法,并通过方法中的对象的引用访问)。 示例(C签名): 所需的C#API: 如果有人向我指出一个使用这种API风格的现有C(再次:不是C)库的SWIG生成的包装器,我也会很高兴;我什么

  • 问题内容: 我正在将MongoDB与Java结合使用,并且对我的连接存在一些问题。首先,我应该如何连接到Mongo?我应该使用静态客户端并保持打开状态吗?因为连接大约需要500毫秒。因此,在用户需要数据时始终连接它不是最好的主意吗? 但是接下来的问题是。当我进行一些查询时,我收到错误消息或。 那么,我应该如何管理整个MongoDB连接呢?始终等待500毫秒是减慢速度并在10个连接不太好之后重启服务

  • 本文向大家介绍Js面向对象的几种方式相关面试题,主要包含被问及Js面向对象的几种方式时的应答技巧和注意事项,需要的朋友参考一下 1.对象的字面量 var obj = {} 2.创建实例对象 var obj = new Object(); 3.构造函数模式 function fn(){} , new fn(); 4.工厂模式:用一个函数,通过传递参数返回对象。function fn(params){

  • 我们已经讨论了类/对象可以拥有像函数一样的方法,这些方法与函数的区别只是一个额外的self变量。现在我们来学习一个例子。 使用对象的方法 例11.2 使用对象的方法 #!/usr/bin/python # Filename: method.py classPerson:     defsayHi(self):         print'Hello, how are you?' p = Perso

  • (假设Magic是4个字节,Command是1个字节,Options是2个字节,Bodysize是4个字节,并且body本身的长度是可变的。)我如何在不使用任何第三方库的情况下解析它? 通常我会说,可以这样做来存储数据包数据: 问题是,我首先提供头信息,然后以一种笨拙的方式添加正文数据。包对象有一个在不完整状态下可以访问的时间点。 我是用C++开发的,对于通过套接字发送和接收数据,使用了boost

  • 本章详细讲述了Python中的各种内置函数,文件I/O操作和重载概念。 Python Built-in Functions Python解释器有许多称为内置函数的函数,可以随时使用。 在其最新版本中,Python包含68个内置函数,如下表所示 - 内置功能 abs() dict() help() min() setattr() all() dir() hex() next() slice() an