Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android SQLite数据库关闭查询()_Android_Sqlite - Fatal编程技术网

Android SQLite数据库关闭查询()

Android SQLite数据库关闭查询(),android,sqlite,Android,Sqlite,我看到ContentProvider.query()返回一个游标对象。通常,游标是SQLiteDatabase查询的结果。如下代码段所示: public Cursor query() { try { SQLiteDatabase db = this.getReadableDatabase(); Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, nu

我看到ContentProvider.query()返回一个游标对象。通常,游标是SQLiteDatabase查询的结果。如下代码段所示:

public Cursor query() {     
        try {
            SQLiteDatabase db = this.getReadableDatabase(); 
            Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, null, null, null, null);
            return c;
        }
        catch(Exception exp) {
        }

        return null;
    }

在代码中,db未关闭。有什么问题吗?

完成后是否尝试关闭数据库? 如果是,请尝试:

public Cursor query() {
        SQLiteDatabase db = null;   
        try {
            SQLiteDatabase db = this.getReadableDatabase(); 
            Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, null, null, null, null);
            return c;
        }
        catch(Exception exp) {
        }finally{
           try{if(null != db){ db.close(); db = null;}}catch(Exception e){}
        }

        return null;
    }
每次都应该正确关闭数据库。如果您想知道为什么它没有关闭,我会调查捕获的异常是什么意思

顺便说一下,我会用null替换“newstring[]{“*”}”。

更新:好了,现在我明白问题了。不过,您可能需要重新构造您的类

TLDR:对我来说,理想的结局是两门课。一个是帮助你打开数据库。第二种方法是将SQLiteDatabase对象作为属性保存。您可以在创建此类(或创建用于打开数据库的方法)后立即打开连接并初始化DB对象。所有方法仅将db对象用于SCUD。然后,所有db对象关闭或分解都可以放在一个方法或重写onDestroy中。 下面的例子,但如果你有时间,这是一个很好的教程

第一个是DBOpenHelper。此类的目的是管理表,并帮助您打开数据库进行修改

package com.mondial.th.rsa.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * DBOpenHelper helps opening database and managing database's upgrade or creation.
 * @author Poohdish Rattanavijai
 *
 */
public class DBOpenHelper extends SQLiteOpenHelper {
    private static final String TAG = DBOpenHelper.class.getSimpleName();
    private static final int DATABASE_VERSION = 2;
    private static final String DATABASE_NAME = "rsa_db";

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

    public DBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase database) {
        Log.d(TAG, "DBOpenHelper.onCreate");
        // Create table goes here.
    }

    @Override
    public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
        // Drop and recreate table goes here.
    }

}
第二个类将使用前面显示的DBOpenHelper为您处理所有查询

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.mondial.th.rsa.vo.ProfileVO;

/**
 * Database adapter for managing Profile table
 * @author Poohdish Rattanavijai
 *
 */
public class ProfileDBAdapter {
    private static final String TAG = ProfileDBAdapter.class.getName();
    private Context context;
    private SQLiteDatabase db;
    private DBOpenHelper dbHelper;

    public ProfileDBAdapter(Context context){
        this.context = context;
    }

    /**
     * Open writable database.
     * @return writable SQLDatabase
     * @throws SQLException
     */
    public ProfileDBAdapter open() throws SQLException{
        Log.d(TAG, "Open ProfileDBAdapter");
        dbHelper = new DBOpenHelper(context);

        db = dbHelper.getWritableDatabase();
        return this;
    }

    /**
     * Close database; Exception omitted
     */
    public void close(){
        try {
            dbHelper.close();
        } catch (Exception e) {
            //e.printStackTrace();
        }
    }

    /**
     * Creating new record in profile table with given VO.
     * @param profile VO representing data in the new record.
     * @return the row ID of the newly inserted row, or -1 if an error occurred.
     */
    public long createProfile(ProfileVO profile){
        ContentValues values = createContentValues(profile);
        return db.insert(ProfileVO.TABLE_NAME, null, values);
    }

    /**
     * Updating record in profile table with given VO by using ID column.
     * @param profile VO representing new data to updated.
     * @return the number of rows affected .
     */
    public boolean updateProfile(ProfileVO profile){
        ContentValues values = createContentValues(profile);
        return db.update(ProfileVO.TABLE_NAME, values, ProfileVO.COLUMN_ID + "=" + profile.getId(), null) > 0;
    }

    /**
     * Deleting a row representing given VO off profile table by using ID column.
     * @param profile
     * @return
     */
    public boolean deleteProfile(ProfileVO profile){
        return deleteProfile(profile.getId());
    }

    /**
     * Deleting a row off profile table with given ID column.
     * @param profile
     * @return
     */
    public boolean deleteProfile(long rowId){
        return db.delete(ProfileVO.TABLE_NAME, ProfileVO.COLUMN_ID + "=" + rowId, null) > 0;
    }

    /**
     * open cursor representing every records in profile table.
     * @return Cursor representing every records in profile table.
     */
    public Cursor fetchAllProfiles(){
        return db.query(ProfileVO.TABLE_NAME, null, null, null, null, null, null);
    }

    /**
     * open cursor representing a row in profile table with given ID.
     * @return Cursor representing a row in profile table with given ID.
     */
    public Cursor fetchProfile(long rowId){
        Cursor mCursor = db.query(true, ProfileVO.TABLE_NAME, null, ProfileVO.COLUMN_ID + "=" + rowId
                , null, null, null, null, null);

        if(null != mCursor){
            mCursor.moveToFirst();
        }

        return mCursor;
    }

    /**
     * This class translate given VO into ContentValues for ContentResolver to parse data and talk to the database.
     * @param profile VO
     * @return ContentsValues containing given VO's data except ID.
     */
    private ContentValues createContentValues(ProfileVO profile){
        ContentValues values = new ContentValues();

        values.put(ProfileVO.COLUMN_DOB, profile.getDob());
        values.put(ProfileVO.COLUMN_FIRSTNAME, profile.getFirstname());
        values.put(ProfileVO.COLUMN_LASTNAME, profile.getLastname());

        return values;
    }
}
然后你就有了一个完美的类来充当刀。对于上面的示例,用法是

ProfileDBAdapter dbHelper = new ProfileDBAdapter(context);
dbHelper.open();
cursor = dbHelper.fetchAllProfiles();
if(cursor.getCount() > 0){
 //TODO Data exists, do stuff.
}
try {
    if(null != cursor && !cursor.isClosed()){
       cursor.close();
    }
} catch (Exception e) {
    e.printStackTrace();
}

if(null != dbHelper){
    dbHelper.close();
    dbHelper = null;
}

您是否正在尝试在完成时关闭数据库? 如果是,请尝试:

public Cursor query() {
        SQLiteDatabase db = null;   
        try {
            SQLiteDatabase db = this.getReadableDatabase(); 
            Cursor c = db.query(Cfg.table_name, new String[] {"*"}, null, null, null, null, null);
            return c;
        }
        catch(Exception exp) {
        }finally{
           try{if(null != db){ db.close(); db = null;}}catch(Exception e){}
        }

        return null;
    }
每次都应该正确关闭数据库。如果您想知道为什么它没有关闭,我会调查捕获的异常是什么意思

顺便说一下,我会用null替换“newstring[]{“*”}”。

更新:好了,现在我明白问题了。不过,您可能需要重新构造您的类

TLDR:对我来说,理想的结局是两门课。一个是帮助你打开数据库。第二种方法是将SQLiteDatabase对象作为属性保存。您可以在创建此类(或创建用于打开数据库的方法)后立即打开连接并初始化DB对象。所有方法仅将db对象用于SCUD。然后,所有db对象关闭或分解都可以放在一个方法或重写onDestroy中。 下面的例子,但如果你有时间,这是一个很好的教程

第一个是DBOpenHelper。此类的目的是管理表,并帮助您打开数据库进行修改

package com.mondial.th.rsa.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * DBOpenHelper helps opening database and managing database's upgrade or creation.
 * @author Poohdish Rattanavijai
 *
 */
public class DBOpenHelper extends SQLiteOpenHelper {
    private static final String TAG = DBOpenHelper.class.getSimpleName();
    private static final int DATABASE_VERSION = 2;
    private static final String DATABASE_NAME = "rsa_db";

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

    public DBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase database) {
        Log.d(TAG, "DBOpenHelper.onCreate");
        // Create table goes here.
    }

    @Override
    public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
        // Drop and recreate table goes here.
    }

}
第二个类将使用前面显示的DBOpenHelper为您处理所有查询

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.mondial.th.rsa.vo.ProfileVO;

/**
 * Database adapter for managing Profile table
 * @author Poohdish Rattanavijai
 *
 */
public class ProfileDBAdapter {
    private static final String TAG = ProfileDBAdapter.class.getName();
    private Context context;
    private SQLiteDatabase db;
    private DBOpenHelper dbHelper;

    public ProfileDBAdapter(Context context){
        this.context = context;
    }

    /**
     * Open writable database.
     * @return writable SQLDatabase
     * @throws SQLException
     */
    public ProfileDBAdapter open() throws SQLException{
        Log.d(TAG, "Open ProfileDBAdapter");
        dbHelper = new DBOpenHelper(context);

        db = dbHelper.getWritableDatabase();
        return this;
    }

    /**
     * Close database; Exception omitted
     */
    public void close(){
        try {
            dbHelper.close();
        } catch (Exception e) {
            //e.printStackTrace();
        }
    }

    /**
     * Creating new record in profile table with given VO.
     * @param profile VO representing data in the new record.
     * @return the row ID of the newly inserted row, or -1 if an error occurred.
     */
    public long createProfile(ProfileVO profile){
        ContentValues values = createContentValues(profile);
        return db.insert(ProfileVO.TABLE_NAME, null, values);
    }

    /**
     * Updating record in profile table with given VO by using ID column.
     * @param profile VO representing new data to updated.
     * @return the number of rows affected .
     */
    public boolean updateProfile(ProfileVO profile){
        ContentValues values = createContentValues(profile);
        return db.update(ProfileVO.TABLE_NAME, values, ProfileVO.COLUMN_ID + "=" + profile.getId(), null) > 0;
    }

    /**
     * Deleting a row representing given VO off profile table by using ID column.
     * @param profile
     * @return
     */
    public boolean deleteProfile(ProfileVO profile){
        return deleteProfile(profile.getId());
    }

    /**
     * Deleting a row off profile table with given ID column.
     * @param profile
     * @return
     */
    public boolean deleteProfile(long rowId){
        return db.delete(ProfileVO.TABLE_NAME, ProfileVO.COLUMN_ID + "=" + rowId, null) > 0;
    }

    /**
     * open cursor representing every records in profile table.
     * @return Cursor representing every records in profile table.
     */
    public Cursor fetchAllProfiles(){
        return db.query(ProfileVO.TABLE_NAME, null, null, null, null, null, null);
    }

    /**
     * open cursor representing a row in profile table with given ID.
     * @return Cursor representing a row in profile table with given ID.
     */
    public Cursor fetchProfile(long rowId){
        Cursor mCursor = db.query(true, ProfileVO.TABLE_NAME, null, ProfileVO.COLUMN_ID + "=" + rowId
                , null, null, null, null, null);

        if(null != mCursor){
            mCursor.moveToFirst();
        }

        return mCursor;
    }

    /**
     * This class translate given VO into ContentValues for ContentResolver to parse data and talk to the database.
     * @param profile VO
     * @return ContentsValues containing given VO's data except ID.
     */
    private ContentValues createContentValues(ProfileVO profile){
        ContentValues values = new ContentValues();

        values.put(ProfileVO.COLUMN_DOB, profile.getDob());
        values.put(ProfileVO.COLUMN_FIRSTNAME, profile.getFirstname());
        values.put(ProfileVO.COLUMN_LASTNAME, profile.getLastname());

        return values;
    }
}
然后你就有了一个完美的类来充当刀。对于上面的示例,用法是

ProfileDBAdapter dbHelper = new ProfileDBAdapter(context);
dbHelper.open();
cursor = dbHelper.fetchAllProfiles();
if(cursor.getCount() > 0){
 //TODO Data exists, do stuff.
}
try {
    if(null != cursor && !cursor.isClosed()){
       cursor.close();
    }
} catch (Exception e) {
    e.printStackTrace();
}

if(null != dbHelper){
    dbHelper.close();
    dbHelper = null;
}

是的,我认为有一个问题。您可以将“db”作为参数传递,然后调用方可以在使用光标时关闭它。

是的,我认为存在问题。您可以将“db”作为参数传递,然后调用方可以在使用光标时将其关闭。

谢谢,但问题是,关闭db后,光标变得无效。我更新了答案。它有点长,有点曲折,但这会帮助你解决问题。谢谢你的回答!您的解决方案解决了当用户可以获取dbHelper对象时的问题。但在我的例子中,用户无法获取dbHelper对象,因为查询是在content provider上进行的。所以,我不能期望用户关闭数据库。谢谢,但问题是关闭数据库后,光标变得无效。我更新了答案。它有点长,有点曲折,但这会帮助你解决问题。谢谢你的回答!您的解决方案解决了当用户可以获取dbHelper对象时的问题。但在我的例子中,用户无法获取dbHelper对象,因为查询是在content provider上进行的。所以,我不能期望用户关闭数据库。