【问题标题】:Insert, Delete, Retrieve data from and into existing sqlite database in assests folder在 assets 文件夹中的现有 sqlite 数据库中插入、删除、检索数据
【发布时间】:2018-11-12 07:38:49
【问题描述】:

我创建了一个 sqlite 数据库并将其放在我的 android 项目的 assets 文件夹中。现在我想在这个数据库上执行Insert,Delete,Retrieve 操作。

我创建了一个新活动,我将在其中输入一个人的详细信息,然后我将按下保存按钮 (checkout_btn) 以将该信息保存在现有数据库中。

我不知道这段代码有什么问题。我没有收到任何错误,甚至数据也没有插入到现有数据库中。

我还想根据此应用程序中用户功能提供的搜索框值添加从数据库中检索数据(on button click)

这是我的代码:

 This class talk about my database which is already present in my assets folder in my project. In this database only i have to insert my data from a form.

**DBConstant.Java**

public abstract class DBConstant
{ //database file directory
public static String DATABASE_PATH = "/data/data/activity.test/databases";
//database file name
public static String DATABASE_FILE = "test.db";
//database version
public static int DATABASE_VERSION = 1;
}

**This is my DBOpenHelper.Java file**

**DBOpenHelper.Java**


public class DBOpenHelper extends SQLiteOpenHelper {

public DBOpenHelper(Context context, String path, int version){
    super(context, path, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}

}

**Below is my DBOperator.Java file**



/**
* Class to manipulate tables & data
* Uses singleton pattern to create single instance
*/
public class DBOperator
{
private static DBOperator instance = null;
private SQLiteDatabase db;

private DBOperator()
{
    //path of database file
    String path = DBConstant.DATABASE_PATH + "/" + DBConstant.DATABASE_FILE;
    db = SQLiteDatabase.openDatabase(path, null, 
SQLiteDatabase.OPEN_READWRITE);
}
/*
 * Singleton Pattern
 * Why should we avoid multiple instances here?
 */
public static DBOperator getInstance()
{
    if (instance==null) instance = new DBOperator();
    return instance;
}
/**
 * Copy database file
 * From assets folder (in the project) to android folder (on device)
 */
public static void copyDB(Context context) throws 
IOException,FileNotFoundException{
    String path = DBConstant.DATABASE_PATH + "/" + DBConstant.DATABASE_FILE;
    File file = new File(path);
    if (!file.exists()){
        DBOpenHelper dbhelper = new DBOpenHelper(context, path ,1);
        dbhelper.getWritableDatabase();
        InputStream is = context.getAssets().open(DBConstant.DATABASE_FILE);
        OutputStream os = new FileOutputStream(file);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer))>0){
            os.write(buffer, 0, length);
        }
        is.close();
        os.flush();
        os.close();
    }
 }
 /**
 * execute sql without returning data, such as alter
 * @param sql
 */
 public void execSQL(String sql) throws SQLException
 {
    db.execSQL(sql);
 }
 /**
 * execute sql such as update/delete/insert
 * @param sql
 * @param args
 * @throws SQLException
 */
 public void execSQL(String sql, Object[] args) throws SQLException
 {
    db.execSQL(sql, args);
 }
/**
 * execute sql query
 * @param sql
 * @param selectionArgs
 * @return cursor
 * @throws SQLException
 */
public Cursor execQuery(String sql,String[] selectionArgs) throws 
SQLException
{
    return db.rawQuery(sql, selectionArgs);
}
/**
 * execute query without arguments
 * @param sql
 * @return
 * @throws SQLException
 */
public Cursor execQuery(String sql) throws SQLException
{
    return this.execQuery(sql, null);
}
/**
 * close database
 */
public void closeDB()
{
    if (db!=null) db.close();
}
}


Here is my DBOperator.Java

/**
* Class to manipulate tables & data
* Uses singleton pattern to create single instance
*/
public class DBOperator
{
private static DBOperator instance = null;
private SQLiteDatabase db;

private DBOperator()
{
    //path of database file
    String path = DBConstant.DATABASE_PATH + "/" + DBConstant.DATABASE_FILE;
    db = SQLiteDatabase.openDatabase(path, null, 
SQLiteDatabase.OPEN_READWRITE);
}
/*
 * Singleton Pattern
 * Why should we avoid multiple instances here?
 */
public static DBOperator getInstance()
{
    if (instance==null) instance = new DBOperator();
    return instance;
}
/**
 * Copy database file
 * From assets folder (in the project) to android folder (on device)
 */
public static void copyDB(Context context) throws 
IOException,FileNotFoundException{
    String path = DBConstant.DATABASE_PATH + "/" + DBConstant.DATABASE_FILE;
    File file = new File(path);
    if (!file.exists()){
        DBOpenHelper dbhelper = new DBOpenHelper(context, path ,1);
        dbhelper.getWritableDatabase();
        InputStream is = context.getAssets().open(DBConstant.DATABASE_FILE);
        OutputStream os = new FileOutputStream(file);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer))>0){
            os.write(buffer, 0, length);
        }
        is.close();
        os.flush();
        os.close();
    }
}

/**
 * execute sql without returning data, such as alter
 * @param sql
 */
public void execSQL(String sql) throws SQLException
{
    db.execSQL(sql);
}
/**
 * execute sql such as update/delete/insert
 * @param sql
 * @param args
 * @throws SQLException
 */
public void execSQL(String sql, Object[] args) throws SQLException
{
    db.execSQL(sql, args);
}
/**
 * execute sql query
 * @param sql
 * @param selectionArgs
 * @return cursor
 * @throws SQLException
 */
public Cursor execQuery(String sql,String[] selectionArgs) throws 
SQLException
{
    return db.rawQuery(sql, selectionArgs);
}
/**
 * execute query without arguments
 * @param sql
 * @return
 * @throws SQLException
 */
public Cursor execQuery(String sql) throws SQLException
{
    return this.execQuery(sql, null);
}
/**
 * close database
 */
public void closeDB()
{
    if (db!=null) db.close();
}
}

NewActivity.java

public class NewpActivity extends AppCompatActivity
{
String PaFirstName,PaLastName,PaDOB,PaGender,PaContact,PaStreetAPT,PaCity,PaState,country,PaPincode,PaInsurance;
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    setContentView(R.layout.activity_newp);
    Button signUpBtn = (Button) findViewById(R.id.checkout_btn);
    signUpBtn.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            //Running method for updating string variables from input boxes
            getValues();
            DBOperator.getInstance().execSQL(SQLCommand.NEW_USER, getArgs());
            Toast.makeText(getBaseContext(), "Checkout successfully", Toast.LENGTH_SHORT).show();

        }


    });
}

SQLCommand.java

public abstract class SQLCommand {
    public static String NEW_USER = "insert into Patient(PaFirstName,PaLastName,PaDOB,PaGender,PaContact,PaStreetAPT,PaCity,PaState,PaPincode,PaInsurance) values(?,?,?,?,?,?,?,?,?,?)";
}

【问题讨论】:

  • 您的路径变量指向本地 db 文件夹而不是 assests 文件夹,您确定要使用该数据库吗?
  • 是的。它是我的应用程序中存在的本地数据库。本地数据库存储在 assets 文件夹中(我在我的应用程序中创建以在本地存储我的数据库)
  • 资产文件夹是只读的

标签: java android sqlite android-studio


【解决方案1】:

问题 1 - 未调用 DBOperator copyDB 方法。

您需要调用 copyDB 方法,以便从 assets 文件夹中复制数据库。否则将创建一个空数据库。

这应该在尝试获取 DBOperator 实例之前完成。设置 Activity 的 ContentView 后立即调用此调用的方便位置,例如

public class NewpActivity extends AppCompatActivity {
    String PaFirstName, PaLastName, PaDOB, PaGender, PaContact, PaStreetAPT, PaCity, PaState, country, PaPincode, PaInsurance;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        setContentView(R.layout.activity_newp);
        Button signUpBtn = (Button) findViewById(R.id.checkout_btn);
        try {
            DBOperator.copyDB(this);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("DB Copy Failed. Issuing runtime exception");
        }
        signUpBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Running method for updating string variables from input boxes
                //getValues();
                //DBOperator.getInstance().execSQL(SQLCommand.NEW_USER, getArgs());
                Toast.makeText(getBaseContext(), "Checkout successfully", Toast.LENGTH_SHORT).show();
            }
        });
    }
}
  • 请注意,在运行更正的代码之前,您应该删除应用程序的数据或卸载应用程序,以便删除数据库(否​​则 copyDB 方法不会复制数据库,因为它存在。)

  • 为方便起见,注释掉了行。

问题 2 -(不是错误)

最好不要硬编码数据库路径,而是通过the_context.getDatabasePath(database_name).getPath 方法检索它。

因此建议您更改:-

String path = DBConstant.DATABASE_PATH + "/" + DBConstant.DATABASE_FILE;

改为:-

String path = context.getDatabasePath(DBConstant.DATABASE_FILE).getPath();

其他内容

  1. 首先,可能需要确认数据库包含预期的表,然后添加代码(在 Activit 的 onCreate 方法中,在其他所有内容之后)

如“-”

public class NewpActivity extends AppCompatActivity {
    String PaFirstName, PaLastName, PaDOB, PaGender, PaContact, PaStreetAPT, PaCity, PaState, country, PaPincode, PaInsurance;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        setContentView(R.layout.activity_newp);
        Button signUpBtn = (Button) findViewById(R.id.checkout_btn);
        try {
            DBOperator.copyDB(this);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("DB Copy Failed. Issuing runtime exception");
        }
        signUpBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Running method for updating string variables from input boxes
                //getValues();
                //DBOperator.getInstance().execSQL(SQLCommand.NEW_USER, getArgs());
                Toast.makeText(getBaseContext(), "Checkout successfully", Toast.LENGTH_SHORT).show();
            }
        });

        //<<<<<<<<<< ADDED TO CONFIRM DATABASE IS AS EXPECTED
        DBOperator checkit = DBOperator.getInstance();
        Cursor csr = checkit.execQuery("SELECT * FROM sqlite_master");
        while (csr.moveToNext()) {
            Log.d(
                    "DBINFO",
                    "Item with a name of " + csr.getString(csr.getColumnIndex("name")) +
                            " and a type of " + csr.getString(csr.getColumnIndex("type")) +
                            " found in the Database."
            );
        }
    }
}
  • 注意以上是如何从表中获取数据并对其进行处理的示例,它使用您的 execQuery 方法(有效)。

    1. 如果数据库没有被复制到 assets 文件夹并且使用了上面的代码,那么你会得到一个类似于
    2. 的错误

:-

11-12 10:17:01.494 2025-2025/? W/System.err: java.io.FileNotFoundException: fail.db
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.content.res.AssetManager.openAsset(Native Method)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:315)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.content.res.AssetManager.open(AssetManager.java:289)
11-12 10:17:01.494 2025-2025/? W/System.err:     at test.activity.test.DBOperator.copyDB(DBOperator.java:54)
11-12 10:17:01.494 2025-2025/? W/System.err:     at test.activity.test.NewpActivity.onCreate(NewpActivity.java:21)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.app.Activity.performCreate(Activity.java:5008)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.app.ActivityThread.access$600(ActivityThread.java:130)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.os.Looper.loop(Looper.java:137)
11-12 10:17:01.494 2025-2025/? W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:4745)
11-12 10:17:01.494 2025-2025/? W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
11-12 10:17:01.494 2025-2025/? W/System.err:     at java.lang.reflect.Method.invoke(Method.java:511)
11-12 10:17:01.494 2025-2025/? W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
11-12 10:17:01.494 2025-2025/? W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-12 10:17:01.494 2025-2025/? W/System.err:     at dalvik.system.NativeStart.main(Native Method)
11-12 10:17:01.494 2025-2025/? D/AndroidRuntime: Shutting down VM
11-12 10:17:01.494 2025-2025/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa62a3288)
11-12 10:17:01.494 2025-2025/? E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{test.activity.test/test.activity.test.NewpActivity}: java.lang.RuntimeException: DB Copy Failed. Issuing runtime exception
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
        at android.app.ActivityThread.access$600(ActivityThread.java:130)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.RuntimeException: DB Copy Failed. Issuing runtime exception
        at test.activity.test.NewpActivity.onCreate(NewpActivity.java:24)
        at android.app.Activity.performCreate(Activity.java:5008)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 
        at android.app.ActivityThread.access$600(ActivityThread.java:130) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:137) 
        at android.app.ActivityThread.main(ActivityThread.java:4745) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:511) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
        at dalvik.system.NativeStart.main(Native Method) 
  • 通过将数据库名称更改为 fail.db 来强制失败
  • 请注意,有两个异常,一个是原始捕获的异常 (),另一个是发出的运行时异常(你必须有一个 try/catch,因为 copyDB 方法会抛出一个异常,所以不妨抛出一个运行时异常)

    1. 良好的运行(复制数据库或不复制数据库,如果它已经存在)将记录以下输出(如果您有更多的表或其他项目,例如索引、触发器、视图,可能会更多)

:-

11-12 09:59:08.910 1917-1917/test.activity.test D/DBINFO: Item with a name of patient and a type of table found in the Database.
11-12 09:59:08.910 1917-1917/test.activity.test D/DBINFO: Item with a name of android_metadata and a type of table found in the Database.

我还想从数据库中添加检索数据(单击按钮) 基于此用户功能提供的搜索框值 应用。

您现在应该尝试这样做,如果您有问题,那么您应该提出一个新问题。你需要决定你想怎么做。您想搜索各个列吗?您是否希望在键入时更改结果,或者您希望单击以启动搜索。也许下拉选择器(Spinner)可以用于某些列,例如当会有一组特定的值时说性别。

【讨论】:

  • 我正在尝试调试并收到此消息:未加载类:wpi.ehr.constant.SQLCommand ...我尝试清理和重建项目仍然没有运气。
【解决方案2】:

在copy db方法中,需要在flush outpustream后关闭inputstream。

现有代码:

public static void copyDB(Context context) throws 
IOException,FileNotFoundException{
    String path = DBConstant.DATABASE_PATH + "/" + DBConstant.DATABASE_FILE;
    File file = new File(path);
    if (!file.exists()){
        DBOpenHelper dbhelper = new DBOpenHelper(context, path ,1);
        dbhelper.getWritableDatabase();
        InputStream is = context.getAssets().open(DBConstant.DATABASE_FILE);
        OutputStream os = new FileOutputStream(file);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer))>0){
            os.write(buffer, 0, length);
        }
        **is.close();
        os.flush();
        os.close();**
    }
}

更新代码:

public static void copyDB(Context context) throws 
IOException,FileNotFoundException{
    String path = DBConstant.DATABASE_PATH + "/" + DBConstant.DATABASE_FILE;
    File file = new File(path);
    if (!file.exists()){
        DBOpenHelper dbhelper = new DBOpenHelper(context, path ,1);
        dbhelper.getWritableDatabase();
        InputStream is = context.getAssets().open(DBConstant.DATABASE_FILE);
        OutputStream os = new FileOutputStream(file);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer))>0){
            os.write(buffer, 0, length);
        }

        **os.flush();os.close();        
       is.close();**
    }
}

【讨论】:

    猜你喜欢
    • 2012-04-07
    • 2013-04-27
    • 2019-07-17
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 2015-12-28
    • 2011-11-29
    • 2018-07-15
    相关资源
    最近更新 更多