Java Driver在cursor.hasNext()上抛出空指针

时间:2013-06-17 00:17:33

标签: java mongodb

Java Driver在cursor.hasNext()

上抛出空指针异常
_collection  = db.getCollection("users");
DBCursor cursor = _collection.find();
System.out.println( "cursor len " + cursor.size() );
//outputs: "cursor len 2"

try {
   while(cursor.hasNext()) { //Throws null pointer exception
       System.out.println(cursor.next());
   }
} finally {
       cursor.close();
}

mongo shell:
db.users.find()
{ "_id" : ObjectId("51be2534036412d6b648354b"), "name" : "dude" }
{ "_id" : ObjectId("51be4de19234ec062efe4a53"), "name" : "lewbowski" }

为什么? :(

堆栈追踪:

Jun 16, 2013 5:28:36 PM com.mongodb.DBPortPool gotError
WARNING: emptying DBPortPool to localhost/127.0.0.1:27017 b/c of error
java.lang.NullPointerException
at org.v2d2.data.UserDAO.put(UserDAO.java:166)
at org.bson.BasicBSONCallback._put(BasicBSONCallback.java:174)
at org.bson.BasicBSONCallback.gotObjectId(BasicBSONCallback.java:143)
at org.bson.BasicBSONDecoder.decodeElement(BasicBSONDecoder.java:160)
at org.bson.BasicBSONDecoder._decode(BasicBSONDecoder.java:79)
at org.bson.BasicBSONDecoder.decode(BasicBSONDecoder.java:57)
at com.mongodb.DefaultDBDecoder.decode(DefaultDBDecoder.java:61)
at com.mongodb.Response.<init>(Response.java:83)
at com.mongodb.DBPort.go(DBPort.java:142)
at com.mongodb.DBPort.call(DBPort.java:92)
at com.mongodb.DBTCPConnector.innerCall(DBTCPConnector.java:244)
at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:216)
at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:288)
at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:273)
at com.mongodb.DBCursor._check(DBCursor.java:368)
at com.mongodb.DBCursor._hasNext(DBCursor.java:459)
at com.mongodb.DBCursor.hasNext(DBCursor.java:484)
at org.v2d2.data.UserDAO.<init>(UserDAO.java:76)
at MongoTest.main(MongoTest.java:41)

=============================================== ============

我修复了空指针,但我没有更近。当我尝试从类中获取值时,它们返回null。

public class UserDAO implements DBObject {

private String _name;
private String _id;

private ArrayList<String> _buildServers;
private BasicDBObject _dao;
private DBCollection _collection;


public UserDAO() {  }

public UserDAO(
        String name,
        DB db )
{
    _name     = name;
    _dao      = new BasicDBObject();

    _collection  = db.getCollection("users");


    _dao.put( "name", _name);

    DBCursor cursor = _collection.find();

    System.out.println( "curso len " + cursor.count() );
    try {
       while(cursor.hasNext()) {
           System.out.println( ((UserDAO)cursor.next()).GetName() );
       }
    } finally {
            cursor.close();
    }
}

public void SetName( String value )
{
    _name = value;
}

public String GetName()
{
    return _name;
}

@Override
public boolean containsField(String arg0)
{
    return _dao.containsField( arg0 );
}

@Override
@Deprecated
public boolean containsKey(String arg0)
{
    return _dao.containsKey( arg0 );
}

@Override
public Object get(String arg0)
{
    return _dao.get( arg0 );
}

@Override
public Set<String> keySet()
{
    return _dao.keySet();
}

@Override
public Object put(String arg0, Object arg1)
{
            //Error was being thrown in here added null check but I can't set the values
    if( _dao == null ) _dao = new BasicDBObject();
    return _dao.put( arg0, arg1 );
}

@Override
public void putAll(BSONObject arg0)
{
    // TODO Auto-generated method stub
    _dao.putAll( arg0 );
}

@Override
public void putAll(Map arg0)
{
    // TODO Auto-generated method stub
    _dao.putAll( arg0 );
}

@Override
public Object removeField(String arg0)
{
    // TODO Auto-generated method stub
    return _dao.removeField( arg0 );
}

@Override
public Map toMap()
{
    return _dao.toMap();
}

@Override
public boolean isPartialObject()
{
    // TODO Auto-generated method stub
    return _dao.isPartialObject();
}

@Override
public void markAsPartialObject()
{
    // TODO Auto-generated method stub
    _dao.markAsPartialObject();
}

}

1 个答案:

答案 0 :(得分:1)

您收到的错误是

public Object put(String arg0, Object arg1)
{
    //Error was being thrown in here added null check but I can't set the values
    if( _dao == null ) _dao = new BasicDBObject();
    return _dao.put( arg0, arg1 );
}
正如你所指出的那样。

这是因为当您从数据库中检索项目时,驱动程序本身会调用此方法。

因此,您对集合执行某种find(),并且驱动程序认识到需要为从UserDAO返回的值创建新的find()对象。它将创建一个全新的UserDAO对象(使用默认构造函数,不带参数的对象),然后调用put()从新UserDAO对象的数据库中设置适当的值

因为该对象是一个闪亮的新对象,使用默认的no-args构造函数创建,此时您的_dao字段为空且为空。您正在通过执行空检查并在需要时创建新的检查来正确处理此问题。但是,这确实意味着您在另一个构造函数中设置的所有其他字段(带有名称和数据库的那个)都没有初始化,因为从未调用过该构造函数。

如果需要为所有新对象初始化所有字段,则需要创建一个公共初始化方法,可以在当前为BasicDBObject字段创建新_dao的位置调用该方法。但是,您将遇到此问题,因为您不知道DB字段(例如)应该是什么。

基本上问题是你的UserDAO不应该引用它来自的DB。我知道这听起来与DAO的做法相反,但那是因为通过Java使用MongoDB并不遵循与使用JDBC的SQL数据库相同的模式。在这种情况下,DAO模式并不适合。