Вставлять, удалять, извлекать данные из и в существующую базу данных sqlite в папке Assests - PullRequest
0 голосов
/ 12 ноября 2018

Я создал базу данных sqlite и поместил ее в папку активов моего проекта Android.Теперь я хочу выполнить 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(?,?,?,?,?,?,?,?,?,?)";
}

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

Проблема 1 - Не вызывается метод DBOperator copyDB .

Вам необходимо вызвать метод copyDB для базы данных, которая будет скопирована из папки ресурсов. В противном случае будет создана пустая база данных.

Это должно быть сделано до того, как будет предпринята попытка получить экземпляр DBOperator. Удобное место для этого вызова будет сразу после установки 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. Если база данных не была скопирована в папку ресурсов и использовался код, указанный выше, вы получите сообщение об ошибке

: -

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
  • Обратите внимание, что есть два исключения: исходное перехваченное исключение () и исключение времени выполнения, которое было сгенерировано (необходимо выполнить попытку / перехватить, поскольку метод 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), например скажем для пола, когда будет определенный набор значений.

0 голосов
/ 12 ноября 2018

В методе copy db вам необходимо закрыть входной поток после очистки выходного потока.

существующий код:

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();**
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...