-2

/i am writing probgram that should take xml file and parse it to database. Database worked witohut crashes, but with close() error, before i tried to implement update function, after that program alwayes crashes.

i decided to use update to prevent dublication and update records ^_^ (is there better way?)

bedies i have only one activity, using clothing database onDestroy does not help. And appiared Fatal exeption ( full logcat in the bottom)

Unable to start activity ComponentInfo{com.s1042512.electionvoter/com.s1042512.electionvoter.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0

main class

import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.s1042512.electionvoter.ImageLoader;
import com.s1042512.electionvoter.XMLParser;
import com.s1042512.electionvoter.Candidate;
import com.s1042512.electionvoter.DatabaseHandler;
import com.s1042512.electionvoter.R;

import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.ImageView;

public class MainActivity extends Activity {

    static final String URL = "http://www.inf.ed.ac.uk/teaching/courses/selp/elections/election.xml";
    // XML node keys
    static final String KEY_CANDIDATE = "candidate"; // parent node
    static final String KEY_PHOTO = "photograph";
    static final String KEY_NAME = "name";
    static final String KEY_OFFICE = "office";
    static final String KEY_PROMISES = "promise";
    static final String KEY_STAT = "statement";
    private DatabaseHandler db;
    public void onDestroy(){
            db.close();
        super.onDestroy();

    }
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        db = new DatabaseHandler(this);

        Candidate test = new Candidate("Test", "Test's office", "Test's photo", "Test's promises", "Test's statement", 1,5);
        db.addCandidate(test);

        XMLParser parser = new XMLParser();
        String xml = parser.getXmlFromUrl(URL); // getting XML
        Document doc = parser.getDomElement(xml); // getting DOM element

        NodeList nl = doc.getElementsByTagName(KEY_CANDIDATE);

        for (int i = 0; i < nl.getLength(); i++) {  
            Element e = (Element) nl.item(i);
            NodeList prm = null;
            String prom = "";
            prm = doc.getElementsByTagName("promise");

            if (db.getCandidatesCount() != 0) {
                List<Candidate> clist = db.getAllCandidates();

                boolean checkname = clist.contains(db.getCandidate(parser
                        .getValue(e, KEY_NAME)));

                for (int j = 0; j < prm.getLength(); j++) {
                    prom += parser.getValue(e, KEY_PROMISES, j) + "\n";
                }
                if (!checkname) {
                    Log.d("Insert: ", "Inserting ..");
                    db.addCandidate(new Candidate(parser.getValue(e, KEY_NAME),
                            parser.getValue(e, KEY_OFFICE), parser.getValue(e,
                                    KEY_PHOTO), prom, parser.getValue(e,
                                    KEY_STAT)));
                } else {
                    Log.d("Update: ", "Updating candidate ");
                    Candidate cand = db.getCandidate(parser.getValue(e,
                            KEY_NAME));
                    Candidate update_cand = new Candidate(parser.getValue(e,
                            KEY_NAME), parser.getValue(e, KEY_OFFICE),
                            parser.getValue(e, KEY_PHOTO), prom,
                            parser.getValue(e, KEY_STAT), cand.get_active(),
                            cand.get_ranking());
                    db.updateCandidate(update_cand);
                }
            }
            else{
                Log.d("Insert: ", "Inserting ..");
                db.addCandidate(new Candidate(parser.getValue(e, KEY_NAME),
                        parser.getValue(e, KEY_OFFICE), parser.getValue(e,
                                KEY_PHOTO), prom, parser.getValue(e,
                                KEY_STAT)));
            }




        }
        Log.d("Reading: ", "Reading all candidates..");
        List<Candidate> candidates = db.getAllCandidates();       

        for (Candidate cn : candidates) {
            String log = "Name: "+cn.get_name()+" ,Office: " + cn.get_office() + " , Photo: " + cn.get_photograph()
                    + " , Promisses: " + cn.get_promises()+ " , Statment: " + cn.get_statment();
                // Writing Candidates to log
        Log.d("Name: ", log);

        }

    }


}

helper class

public class DatabaseHandler extends SQLiteOpenHelper {
    // All Static variables
    // Database Version
    private static final int DATABASE_VERSION = 1;

    // Database Name
    private static final String DATABASE_NAME = "ElectionCandidates";

    // Candidates table name
    private static final String TABLE_CANDIDATES = "candidates";

    // Candidates Table Columns names
    private static final String KEY_NAME = "name";
    private static final String KEY_OFFICE = "office";
    private static final String KEY_PHOTO = "photograph";
    private static final String KEY_PROMISSES = "promisses";
    private static final String KEY_STATMENT = "statment";
    private static final String KEY_ACTIVE = "active";
    private static final String KEY_RANKING = "ranking";
    private SQLiteDatabase db;
    private Cursor cursor;


    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);

    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_CANDIDATES_TABLE = "CREATE TABLE " + TABLE_CANDIDATES
                + "(" + KEY_NAME + " TEXT," + KEY_OFFICE + " TEXT," + KEY_PHOTO
                + " TEXT," + KEY_PROMISSES + " TEXT," + KEY_STATMENT + " TEXT,"
                + KEY_ACTIVE + " TEXT," + KEY_RANKING + " TEXT" + ")";
        db.execSQL(CREATE_CANDIDATES_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_CANDIDATES);

        // Create tables again
        onCreate(db);
    }

    void addCandidate(Candidate candidate) {
        db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, candidate.get_name()); // Candidate Name
        values.put(KEY_OFFICE, candidate.get_office()); // Candidate Phone
        values.put(KEY_PHOTO, candidate.get_photograph());
        values.put(KEY_PROMISSES, candidate.get_promises());
        values.put(KEY_STATMENT, candidate.get_statment());
        values.put(KEY_ACTIVE, 1);
        values.put(KEY_RANKING, 0);

        // Inserting Row
        db.insert(TABLE_CANDIDATES, null, values);
        db.close(); // Closing database connection
    }

    Candidate getCandidate(String name) {
        db = this.getReadableDatabase();

        cursor = db.query(TABLE_CANDIDATES,
                new String[] { KEY_NAME, KEY_OFFICE, KEY_PHOTO, KEY_PROMISSES,
                        KEY_STATMENT, KEY_ACTIVE, KEY_RANKING }, KEY_NAME + "=?",
                new String[] { String.valueOf(name) }, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Candidate candidate = new Candidate(cursor.getString(0),
                cursor.getString(1), cursor.getString(2), cursor.getString(3),
                cursor.getString(4), Integer.parseInt(cursor.getString(5)), Integer.parseInt(cursor.getString(6)));
        // return candidate
        db.close();
        cursor.close();
        return candidate;
    }

    public List<Candidate> getAllCandidates() {
        List<Candidate> candidateList = new ArrayList<Candidate>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_CANDIDATES;

        db = this.getReadableDatabase();
        cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Candidate candidate = new Candidate();
                candidate.set_name(cursor.getString(0));
                candidate.set_office(cursor.getString(1));
                candidate.set_photograph(cursor.getString(2));
                candidate.set_promises(cursor.getString(3));
                candidate.set_statment(cursor.getString(4));
                candidate.set_active(Integer.parseInt(cursor.getString(5)));
                candidate.set_ranking(Integer.parseInt(cursor.getString(6)));

                // Adding candidate to list
                candidateList.add(candidate);
            } while (cursor.moveToNext());
        }

        // return candidate list
        db.close();
        cursor.close();
        return candidateList;
    }

    public int updateCandidate(Candidate candidate) {
        db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, candidate.get_name()); // Candidate Name
        values.put(KEY_OFFICE, candidate.get_office()); // Candidate Phone
        values.put(KEY_PHOTO, candidate.get_photograph());
        values.put(KEY_PROMISSES, candidate.get_promises());
        values.put(KEY_STATMENT, candidate.get_statment());
        values.put(KEY_ACTIVE, candidate.get_active());
        values.put(KEY_RANKING, candidate.get_active());

        // updating row
        return db.update(TABLE_CANDIDATES, values, KEY_NAME + " = ?",
                new String[] { String.valueOf(candidate.get_name()) });
    }

    // Deleting single candidate
    public void deleteCandidate(Candidate candidate) {
        db = this.getWritableDatabase();
        db.delete(TABLE_CANDIDATES, KEY_NAME + " = ?",
                new String[] { String.valueOf(candidate.get_name()) });
        db.close();
    }

    // Getting candidates Count
    public int getCandidatesCount() {
        String countQuery = "SELECT  * FROM " + TABLE_CANDIDATES;
        db = this.getReadableDatabase();
        cursor = db.rawQuery(countQuery, null);

        int count = cursor.getCount();
        cursor.close();
        db.close();
        // return count
        return count;
    }
}

logcat output

12-13 01:36:25.359: D/I was there(338): parsing 
12-13 01:36:25.428: D/AndroidRuntime(338): Shutting down VM
12-13 01:36:25.428: W/dalvikvm(338): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
12-13 01:36:25.479: D/dalvikvm(338): GC_FOR_MALLOC freed 3868 objects / 251528 bytes in 53ms
12-13 01:36:25.488: E/Cursor(338): Finalizing a Cursor that has not been deactivated or closed. database = /data/data/com.s1042512.electionvoter/databases/ElectionCandidates, table = candidates, query = SELECT name, office, photograph, promisses, statment, active, ranking FROM candidates WHERE name=?
12-13 01:36:25.488: E/Cursor(338): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
12-13 01:36:25.488: E/Cursor(338):  at android.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:210)
12-13 01:36:25.488: E/Cursor(338):  at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53)
12-13 01:36:25.488: E/Cursor(338):  at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1345)
12-13 01:36:25.488: E/Cursor(338):  at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1229)
12-13 01:36:25.488: E/Cursor(338):  at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1184)
12-13 01:36:25.488: E/Cursor(338):  at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1264)
12-13 01:36:25.488: E/Cursor(338):  at com.s1042512.electionvoter.DatabaseHandler.getCandidate(DatabaseHandler.java:80)
12-13 01:36:25.488: E/Cursor(338):  at com.s1042512.electionvoter.MainActivity.onCreate(MainActivity.java:58)
12-13 01:36:25.488: E/Cursor(338):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-13 01:36:25.488: E/Cursor(338):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
12-13 01:36:25.488: E/Cursor(338):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
12-13 01:36:25.488: E/Cursor(338):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
12-13 01:36:25.488: E/Cursor(338):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
12-13 01:36:25.488: E/Cursor(338):  at android.os.Handler.dispatchMessage(Handler.java:99)
12-13 01:36:25.488: E/Cursor(338):  at android.os.Looper.loop(Looper.java:123)
12-13 01:36:25.488: E/Cursor(338):  at android.app.ActivityThread.main(ActivityThread.java:4627)
12-13 01:36:25.488: E/Cursor(338):  at java.lang.reflect.Method.invokeNative(Native Method)
12-13 01:36:25.488: E/Cursor(338):  at java.lang.reflect.Method.invoke(Method.java:521)
12-13 01:36:25.488: E/Cursor(338):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-13 01:36:25.488: E/Cursor(338):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-13 01:36:25.488: E/Cursor(338):  at dalvik.system.NativeStart.main(Native Method)
12-13 01:36:25.508: W/SQLiteCompiledSql(338): Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: SELECT name, office, photograph, promisses, statment, active, ranking FROM candidates WHERE name=?
12-13 01:36:25.508: W/SQLiteCompiledSql(338): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:80)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:46)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1345)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1229)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1184)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1264)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at com.s1042512.electionvoter.DatabaseHandler.getCandidate(DatabaseHandler.java:80)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at com.s1042512.electionvoter.MainActivity.onCreate(MainActivity.java:58)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.app.ActivityThread.access$2300(ActivityThread.java:125)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.os.Handler.dispatchMessage(Handler.java:99)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.os.Looper.loop(Looper.java:123)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at android.app.ActivityThread.main(ActivityThread.java:4627)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at java.lang.reflect.Method.invokeNative(Native Method)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at java.lang.reflect.Method.invoke(Method.java:521)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-13 01:36:25.508: W/SQLiteCompiledSql(338):   at dalvik.system.NativeStart.main(Native Method)
12-13 01:36:25.518: E/AndroidRuntime(338): FATAL EXCEPTION: main
12-13 01:36:25.518: E/AndroidRuntime(338): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.s1042512.electionvoter/com.s1042512.electionvoter.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.app.ActivityThread.access$2300(ActivityThread.java:125)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.os.Handler.dispatchMessage(Handler.java:99)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.os.Looper.loop(Looper.java:123)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.app.ActivityThread.main(ActivityThread.java:4627)
12-13 01:36:25.518: E/AndroidRuntime(338):  at java.lang.reflect.Method.invokeNative(Native Method)
12-13 01:36:25.518: E/AndroidRuntime(338):  at java.lang.reflect.Method.invoke(Method.java:521)
12-13 01:36:25.518: E/AndroidRuntime(338):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-13 01:36:25.518: E/AndroidRuntime(338):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-13 01:36:25.518: E/AndroidRuntime(338):  at dalvik.system.NativeStart.main(Native Method)
12-13 01:36:25.518: E/AndroidRuntime(338): Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.database.AbstractCursor.checkPosition(AbstractCursor.java:580)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:214)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:41)
12-13 01:36:25.518: E/AndroidRuntime(338):  at com.s1042512.electionvoter.DatabaseHandler.getCandidate(DatabaseHandler.java:87)
12-13 01:36:25.518: E/AndroidRuntime(338):  at com.s1042512.electionvoter.MainActivity.onCreate(MainActivity.java:58)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-13 01:36:25.518: E/AndroidRuntime(338):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
12-13 01:36:25.518: E/AndroidRuntime(338):  ... 11 more
12-13 01:36:25.529: E/Database(338): close() was never explicitly called on database '/data/data/com.s1042512.electionvoter/databases/ElectionCandidates' 
12-13 01:36:25.529: E/Database(338): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
12-13 01:36:25.529: E/Database(338):    at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1810)
12-13 01:36:25.529: E/Database(338):    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
12-13 01:36:25.529: E/Database(338):    at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
12-13 01:36:25.529: E/Database(338):    at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
12-13 01:36:25.529: E/Database(338):    at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
12-13 01:36:25.529: E/Database(338):    at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
12-13 01:36:25.529: E/Database(338):    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
12-13 01:36:25.529: E/Database(338):    at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:158)
12-13 01:36:25.529: E/Database(338):    at com.s1042512.electionvoter.DatabaseHandler.getCandidate(DatabaseHandler.java:78)
12-13 01:36:25.529: E/Database(338):    at com.s1042512.electionvoter.MainActivity.onCreate(MainActivity.java:58)
12-13 01:36:25.529: E/Database(338):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-13 01:36:25.529: E/Database(338):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
12-13 01:36:25.529: E/Database(338):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
12-13 01:36:25.529: E/Database(338):    at android.app.ActivityThread.access$2300(ActivityThread.java:125)
12-13 01:36:25.529: E/Database(338):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
12-13 01:36:25.529: E/Database(338):    at android.os.Handler.dispatchMessage(Handler.java:99)
12-13 01:36:25.529: E/Database(338):    at android.os.Looper.loop(Looper.java:123)
12-13 01:36:25.529: E/Database(338):    at android.app.ActivityThread.main(ActivityThread.java:4627)
12-13 01:36:25.529: E/Database(338):    at java.lang.reflect.Method.invokeNative(Native Method)
12-13 01:36:25.529: E/Database(338):    at java.lang.reflect.Method.invoke(Method.java:521)
12-13 01:36:25.529: E/Database(338):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-13 01:36:25.529: E/Database(338):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-13 01:36:25.529: E/Database(338):    at dalvik.system.NativeStart.main(Native Method)
4

1 回答 1

0

我认为你的错误很简单。您在 DatabaseHandler 中的 153 是包含以下代码的行吗?

return cursor.getCount();

在这一行中,您正在访问在此之前已关闭的游标对象。根据API,游标关闭后无效。

尝试将 getCandidatesCount()-Method 更改为:

public int getCandidatesCount() {
    String countQuery = "SELECT  * FROM " + TABLE_CANDIDATES;
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery(countQuery, null);
    int candidatesCount = cursor.getCount();
    cursor.close();

    // return count
    return candidatesCount;
}

PS:是否有任何理由关闭方法中的游标getCandidate(..)getAllCandidates()

于 2012-12-13T01:22:14.383 回答