简体   繁体   English

在assests文件夹中的现有sqlite数据库中插入数据,将其删除,检索数据

[英]Insert, Delete, Retrieve data from and into existing sqlite database in assests folder

I have created a sqlite database and placed it in assets folder of my android project. 我创建了一个sqlite数据库并将其放在我的android项目的资产文件夹中。 Now i want to perform Insert,Delete,Retrieve operations on this database. 现在,我要在此数据库上执行Insert,Delete,Retrieve操作。

I have created a new activity where i will be entering detail of a person and then i will press save button (checkout_btn) to save that information in existing database. 我创建了一个新活动,在该活动中,我将输入一个人的详细信息,然后按保存按钮(checkout_btn) ,将该信息保存在现有数据库中。

I do not know what is wrong in this code. 我不知道这段代码有什么问题。 I am not getting any error nor even data is getting inserted in existing database. 我没有任何错误,甚至没有数据插入到现有数据库中。

I also want to add Retrieve data (on button click) from database on basis of a search box value provided by user functionality in this application. 我还想根据此应用程序中用户功能提供的搜索框值,从数据库中添加检索数据(on button click)

Here is my code: 这是我的代码:

 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 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 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(?,?,?,?,?,?,?,?,?,?)";
}

In the copy db method,you need to close the inputstream after flushing the outpustream. 在copy db方法中,需要在刷新输出流后关闭输入流。

existing code: 现有代码:

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();**
    }
}

updated code: 更新的代码:

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();**
    }
}

Issue 1 - Not calling the DBOperator copyDB method. 问题1-不调用DBOperator copyDB方法。

You need to call the copyDB method for the Database to be copied from the assets folder. 您需要调用copyDB方法,以便从资产文件夹复制数据库。 Otherwise an empty database will be created. 否则,将创建一个空数据库。

This should be done before an attempt is made to get a DBOperator Instance. 这应该在尝试获取DBOperator实例之前完成。 A convenient place for this call would be immediately after the Activity's ContentView is set eg 设置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();
            }
        });
    }
}
  • Note before running the corrected code you should delete the App's data or uninstall the App so that the database is deleted (otherwise the copyDB method will not copy the database as it exists.) 请注意,在运行更正的代码之前,您应该删除应用程序的数据或卸载应用程序,以便删除数据库(否​​则,copyDB方法将不会复制数据库,因为它已经存在。)

  • Lines commented out for convenience. 为了方便起见,将行注释掉。

Issue 2 - (not an error) 问题2-(不是错误)

It is much better to not hard code the database path but to retrieve it via the_context.getDatabasePath(database_name).getPath method. 最好不要硬编码数据库路径,而最好通过the_context.getDatabasePath(database_name).getPath方法检索它。

As such it is suggested that you change :- 因此建议您更改:-

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

to instead be :- 改为:-

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

Additional Stuff 额外的东西

  1. At first it might be an idea to confirm that the database contains the expected table(s), adding code (in the Activit's onCreate method after everything else) 最初,可能要先确认数据库包含预期的表,然后添加代码(在Activit的onCreate方法中执行所有其他操作)

such as "- 如 ”-

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."
            );
        }
    }
}
  • Note the above is an example of how you can get data from a table and process it and it uses your execQuery method (which works). 请注意 ,以上示例是如何从表中获取数据并对其进行处理的示例,并且该示例使用了execQuery方法(有效)。

    1. Should the database not have been copied to the assets folder and the code above was used then you would get an error along the lines of 如果尚未将数据库复制到资产文件夹,并且使用了上面的代码,则将出现以下错误:

:- :-

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) 
  • The failure was forced by changing the database name to fail.db 通过将数据库名称更改为fail.db来强制失败
  • Note that there are two exceptions the original caught exception () and then the runtime exception that was issued (you have to have a try/catch as the copyDB method throws an exception so might as well throw a runtime exception) 请注意,原始捕获的异常()和发出的运行时异常有两个异常(您必须具有try / catch,因为copyDB方法会引发异常,因此也可能会引发运行时异常)

    1. A good run (that copies the database or doesn't if it already exists) would log the following output (perhaps more if you have more tables or other items wuch an indexes, triggers, views) 一个好的运行(复制数据库或者如果不存在则不复制)将记录以下输出(如果您有更多的表或其他项目,例如索引,触发器,视图,则可能会更多)

:- :-

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.

I also want to add Retrieve data (on button click) from database on basis of a search box value provided by user functionality in this application. 我还想根据此应用程序中用户功能提供的搜索框值,从数据库中添加检索数据(单击按钮时)。

That you should now try doing, if you have issues then you should ask a new question. 现在,您应该尝试执行此操作,如果遇到问题,则应该提出一个新问题。 You'd need to decide how you would want to do it. 您需要决定如何做。 Would you want to search on various columns? 您要搜索各种列吗? would you want the results to change as you typed or would you want to a click to initiate the search. 您是否希望结果随输入而更改,或者您想单击以启动搜索。 Perhaps a drop-down selector (Spinner) could be used for some columns eg say for Gender when there will be a specific set of values. 也许某些字段可以使用下拉选择器(微调器),例如,当存在一组特定的值时,例如用于性别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM