日期:2014-05-16  浏览次数:20559 次

MongoDB Java Driver 源码分析(5):com.mongodb.DB
DB 表示数据库连接,是一个抽象类,部分核心功能由子类提供,由 DBApiLayer 继承。

由子类实现的抽象方法

// 开始数据库连接
public abstract void requestStart();
// 结束数据库连接
public abstract void requestDone();
// 保持数据库连接
public abstract void requestEnsureConnection();

// 获取指定名称的数据集
protected abstract DBCollection doGetCollection( String name );


数据集相关的方法

    // 创建数据集
    public final DBCollection createCollection( String name, DBObject options ){
        // 如果 options 不为空
        // 则先以 options 构造创建数据库的命令
        // 然后执行创建数据库的命令并得到结果
        if ( options != null ){
            DBObject createCmd = new BasicDBObject("create", name);
            createCmd.putAll(options);
            CommandResult result = command(createCmd);
            result.throwOnError();
        }

        return getCollection(name);
    }

    // 解析用 "." 分隔的字符串,获取指定的数据集
    public DBCollection getCollectionFromString( String s ){
        DBCollection foo = null;

        // 获取 "." 所在位置
        int idx = s.indexOf( "." );

        // 当分解后的字符串中仍然包含 "." 时
        // 循环分解字符串,知道所有 "." 号解析完毕
        // 效果类似于递归调用,但这里采用了循环的写法
        while ( idx >= 0 ){
            // 获取 "." 之前的字符串 b
            String b = s.substring( 0 , idx );
            // 获取 "." 之后的字符串 s
            s = s.substring( idx + 1 );

            // 检查上次解析得到的对象 foo 是否为空
            if ( foo == null )
                foo = getCollection( b );
            else
                foo = foo.getCollection( b );

            // 获取 "." 所在位置
            idx = s.indexOf( "." );
        }

        if ( foo != null )
            return foo.getCollection( s );

        return getCollection( s );
    }

    // 获取所有数据集名称
    public Set<String> getCollectionNames()
        throws MongoException {

        // 获取系统的 namespace 数据集
        DBCollection namespaces = getCollection("system.namespaces");
        if (namespaces == null)
            throw new RuntimeException("this is impossible");

        // 获取用于遍历 namespace 的迭代器
        Iterator<DBObject> i = namespaces.__find(new BasicDBObject(), null, 0, 0, 0, getOptions());
        if (i == null)
            return new HashSet<String>();

        // 表名称 List,最后转换为 set 并返回
        List<String> tables = new ArrayList<String>();

        for (; i.hasNext();) {
            DBObject o = i.next();
            if ( o.get( "name" ) == null ){
                throw new MongoException( "how is name null : " + o );
            }

            // 获取 namespace 名称
            String n = o.get("name").toString();

            // 获取 namespace 名称前缀
            int idx = n.indexOf(".");
            String root = n.substring(0, idx);

            // 如果前缀不为当前 DB 的名称
            // 表示这个 namespace 不属于当前 DB
            if (!root.equals(_name))
                continue;

            // 忽略特殊数据集
            if (n.indexOf("$") >= 0)
                continue;

            // 获取数据集名称
            String table = n.substring(idx + 1);

            tables.add(table);
        }

        Collections.sort(tables);

        // 转换为 Set
        return new LinkedHashSet<String>(tables);
    }


数据库命令相关的方法

    // 执行数据库命令
    public CommandResult command( DBObject cmd , int options )
        throws MongoException {

        // 调用 DBCollection 的 find 方法        
        Iterator<DBObject> i = getCollection("$cmd").__find(cmd, new BasicDBObject(), 0, -1, 0, options);
        if ( i == null || ! i.hasNext() )
            return null;
 
        // 获得数据库命令的返回结果结果       
        CommandResult res = (CommandResult)i.next();
        res._cmd = c