0

Java 驱动程序在 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();
}

}

4

1 回答 1

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对象设置适当的值。

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

如果需要为所有新对象初始化所有字段,则需要创建一个通用初始化方法,该方法可以在您当前BasicDBObject为该_dao字段创建新对象的地方调用。但是,您会遇到麻烦,因为您不知道 DB 字段(例如)应该是什么。

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

于 2013-07-01T13:32:16.940 回答