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();
}
}
答案 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模式并不适合。