Android进阶之数据库存储

一、SQLite数据库

1、操作步骤
①建立表结构,DBTable
②建立数据库连接,DBConnection
③命令对象执行SQL语句
④返回操作结果
⑤关闭连接

2、查询数据库表
在FileExplorer/data/data/包名/databases

3、数据库出错如何调试

①首先,检查数据库创建成功没有
②然后,再看数据库打开没有
③接着,检查数据操作代码有问题没

4、Cursor 空指针异常,以为没有初始化
初始化:Cursor cursor = SQLiteDatabase.query(table表名,newString[]{},null,—-);

二、代码演示

1、User.java

package com.guan.dbsignin.model;

/** * 用户对象类 * @author Guan * @file com.guan.store.sqlite * @date 2015/8/31 * @Version 1.0 */
public class User {

    private String userName;
    private String userAddress;

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

2、DBOpenHelper.java 创建数据库中的表,并做适当的初始化工作

/** * DBOpenHelper创建数据库中的表,并做适当的初始化工作 * * SQLiteOpenHelper 中有两个抽象方法,分别是 onCreate()和 onUpgrade() * @author Guan * @file com.guan.store.sqlite * @date 2015/9/1 * @Version 1.0 */
public class DBOpenHelper extends SQLiteOpenHelper {

    private final String DATABASE_NAME = "androidDBStorageSqlite";
    public static final String TABLE_NAME = "users";
    public static final String COLUMN_USERNAME = "userName";
    public static final String COLUMN_USERADDRES = "userAddress";

    public static final String DATABASE_CREATE = "Create TABLE if not exists MAIN.[" + TABLE_NAME + "](\n" +
            "[_id] integer PRIMARY KEY NOT NULL\n" +
            ",[" + COLUMN_USERNAME + "] integer NOT NULL\n" +
            ",[" + COLUMN_USERADDRES + "] integer NOT NULL\n" +
            " \n" +
            ");";

    public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DATABASE_CREATE);
    }

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

        if (newVersion == 2) {
            db.execSQL(DATABASE_CREATE);
        } else if (oldVersion == 2 && newVersion == 1) {
            db.execSQL("drop table MAIN.[" + TABLE_NAME + "]");
        }
    }
}

3、DBOperation.java 数据库操作类

/** * DBOperation实现数据库的各项操作,包括:建立及打开数据库、增、删、改、查等 * * @author Guan * @file com.guan.store.sqlite * @date 2015/8/31 * @Version 1.0 */
public class DBOperation {

    private Context mContext;
    private String firstTabName = null;
    private SQLiteDatabase mSqLiteDatabase;
    private final String DATABASE_NAME = "androidDBStorageSqlite";

    public static final String TABLE_NAME = "users";
    public static final String COLUMN_ID = "id";
    public static final String COLUMN_USERNAME = "userName";
    public static final String COLUMN_USERADDRES = "userAddress";

    public DBOperation(Context pContext) {
        this.mContext = pContext;
    }

    /** * 建立及打开数据库 * * SQLiteOpenHelper 中 还 有 两 个 非 常 重 要 的 实 例 方 法 , getReadableDatabase() 和 getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在 则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。 * 不同的是,当数据库不可写入的时候(如磁盘空间已满)getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而 getWritableDatabase()方法则将出现异常。 */
    public void openOrCreateDatabase() {

        try {
            DBOpenHelper _helper = new DBOpenHelper(mContext,DATABASE_NAME,null,2);
            mSqLiteDatabase = _helper.getWritableDatabase();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /** * 插入用户 * @param user */
    public long insertUser(User user) {

        if (mSqLiteDatabase != null && user != null) {
            // 插入一条记录
            ContentValues values = new ContentValues();
            values.put(COLUMN_USERNAME, user.getUserName());
            values.put(COLUMN_USERADDRES, user.getUserAddress());
            return mSqLiteDatabase.insert(TABLE_NAME, "", values);
        }
        return -1;
    }

    /** * 查询所有记录 */
    public Cursor selectAll() {

        if (mSqLiteDatabase != null) {
            return mSqLiteDatabase.query(TABLE_NAME, new String[]{"_id", COLUMN_USERNAME, COLUMN_USERADDRES}, null, null, null, null, null);
        }

        return null;
    }

    /** * 根据条件查询用户 * @param selection * @param selectionArgs * @param groupBy * @param having * @param orderBy * @return */
    public Cursor selectUser(String selection,String[] selectionArgs,String groupBy,String having,String orderBy) {

        return mSqLiteDatabase.query(TABLE_NAME,new String[]{"_id",COLUMN_USERNAME, COLUMN_USERADDRES},selection,selectionArgs
        ,groupBy,having,orderBy);
    }

    /** * 删除用户 * @param id * @return */
    public int deleteUser(int id) {

        if (mSqLiteDatabase != null && id > 0) {
            return mSqLiteDatabase.delete(TABLE_NAME,"_id=?",new String[]{String.valueOf(id)});
        }
        return -1;
    }

    /** * 更新用户 * @param user * @param id * @return */
    public int updateUser(User user,int id) {

        if (mSqLiteDatabase != null && user != null) {
            ContentValues _values = new ContentValues();
            _values.put(COLUMN_USERNAME,user.getUserName());
            _values.put(COLUMN_USERADDRES,user.getUserAddress());
            return mSqLiteDatabase.update(TABLE_NAME, _values, "_id=?", new String[]{String.valueOf(id)});
        }
        return -1;
    }

    /** * 关闭数据库 */
    public void closeDatabase() {

        mSqLiteDatabase.close();
        mSqLiteDatabase = null;
    }
}

4、activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <RelativeLayout  android:id="@+id/llyt_sign" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal">

        <Button  android:id="@+id/add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="添加" />
    </RelativeLayout>

    <ListView  android:id="@+id/lv_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@id/llyt_sign" android:layout_marginTop="10dp" />

</RelativeLayout>

5、activity_submit.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.guan.dbsignin.activity.SubmitActivity">

    <RelativeLayout  android:id="@+id/llyt_sign" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal">

        <Button  android:id="@+id/bt_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:text="返回" />

        <Button  android:id="@+id/bt_submit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="提交" />
    </RelativeLayout>

    <EditText  android:id="@+id/et_name" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/llyt_sign" android:layout_marginTop="50dp" android:inputType="text" />

</RelativeLayout>

6、adapter_line.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">


        <TextView  android:id="@+id/tv_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_marginTop="16dp" android:layout_gravity="center_vertical" android:layout_marginLeft="8dp" android:text="TextView" />

        <TextView  android:id="@+id/tv_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_alignParentRight="true" android:layout_marginRight="8dp" android:layout_marginTop="40dp" android:text="TextView" />

</RelativeLayout>

7、MainActivity.java

/** * 点击添加按钮跳转到第二个activity,输入的数据要存入到数据库里面 , * 第一个activity显示的内容是第二个activity输入的内容,数据从数据库里面提取。 * 我每次打开activity1界面的时候如果数据库有数据 都要显示出来 */
public class MainActivity extends Activity {


    @Bind(R.id.add)
    Button add;
    @Bind(R.id.lv_text)
    ListView lvText;

    private Cursor mCursor;
    /** * 存储数据的数组列表 */
    private ArrayList<HashMap<String, Object>> mListData;
    /** * 适配器 */
    private SimpleAdapter mListItemAdapter;
    public static DBOperation mDBOperation;
    private static final String TAG = "TAG";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        initVariable();
        getData();
        bindData();
    }

    /** * 初始化变量 */
    private void initVariable() {
        mDBOperation = new DBOperation(MainActivity.this);
        mListData = new ArrayList<HashMap<String, Object>>();

        // 创建数据库
        mDBOperation.openOrCreateDatabase();
    }

    /** * 查询所有数据,并添加到列表中 */
    public void getData() {
        // 获取数据源,查找所有用户
        Cursor cursor = mDBOperation.selectAll();
        if (cursor != null) {
            int columnsSize = cursor.getColumnCount();
            // 获取表的内容
            while (cursor.moveToNext()) {
                HashMap<String, Object> map = new HashMap<String, Object>();
                for (int i = 0; i < columnsSize; i++) {
                    map.put(mDBOperation.COLUMN_ID, cursor.getString(0));
                    map.put(mDBOperation.COLUMN_USERNAME, cursor.getString(1));
                    map.put(mDBOperation.COLUMN_USERADDRES, cursor.getString(2));
                }
                mListData.add(map);
            }
            cursor.close();
        }
    }

    /** * 绑定数据 */
    private void bindData() {

        mCursor = mDBOperation.selectAll();

        mListItemAdapter = new SimpleAdapter(MainActivity.this,
                // 数据源
                mListData,
                // ListItem的XML实现
                R.layout.adapter_line,
                // 动态数组与ImageItem对应的子项
                new String[]{mDBOperation.COLUMN_USERNAME, mDBOperation.COLUMN_USERADDRES},
                // XML文件里面的两个ID
                new int[]{R.id.tv_1, R.id.tv_2});
        lvText.setAdapter(mListItemAdapter);
        lvText.setOnCreateContextMenuListener(listviewLongPress);
    }

    /** * 触发监听 */
    @OnClick(R.id.add)
    public void submit() {
        Intent _intent = new Intent(MainActivity.this, SubmitActivity.class);
        startActivity(_intent);
        this.finish();
    }

    /** * 长按事件响应 */
    View.OnCreateContextMenuListener listviewLongPress = new View.OnCreateContextMenuListener() {
        @Override
        public void onCreateContextMenu(ContextMenu menu, View v,
                                        ContextMenu.ContextMenuInfo menuInfo) {

            final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
            new AlertDialog.Builder(MainActivity.this)
                    .setTitle("删除当前数据")
                    .setIcon(android.R.drawable.ic_dialog_info)
                    .setMessage("确定删除当前记录")
                    .setPositiveButton("是",
                            new DialogInterface.OnClickListener() {

                                public void onClick(
                                        DialogInterface dialoginterface, int i) {
                                    // 获取位置索引
                                    int mListPos = info.position;
                                    // 获取对应HashMap数据内容
                                    HashMap<String, Object> map = mListData
                                            .get(mListPos);
                                    // 获取id
                                    int id = Integer.valueOf((map.get(mDBOperation.COLUMN_ID)
                                            .toString()));
                                    // 获取数组具体值后,可以对数据进行相关的操作
                                    if (mDBOperation.deleteUser(id) != -1) {
                                        // 移除listData的数据
                                        mListData.remove(mListPos);
                                        mListItemAdapter.notifyDataSetChanged();
                                    }
                                }
                            })
                    .setNegativeButton("否",
                            new DialogInterface.OnClickListener() {

                                public void onClick(
                                        DialogInterface dialoginterface, int i) {
                                }
                            }).show();
        }
    };

// public class MainActivity extends ListActivity

// /**
// * 获取数据源
// */
// private void displayData() {
//
// // 获取数据源,查找所有用户
// Cursor cursor = mDBOperation.selectAll();
// if (cursor != null) {
// // 绑定数据源与adapter
// SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, cursor,
// new String[]{mDBOperation.COLUMN_USERNAME, mDBOperation.COLUMN_USERADDRES}, new int[]{android.R.id.text1, android.R.id.text2});
//
// // 绑定adapter到界面
// setListAdapter(adapter);
// }
// }
}

8、SubmitActivity.java

public class SubmitActivity extends AppCompatActivity {

    @Bind(R.id.bt_back)
    Button btBack;
    @Bind(R.id.bt_submit)
    Button btSubmit;
    @Bind(R.id.et_name)
    EditText etName;

    private Intent _intent;
    private SimpleDateFormat sDateFormat;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_submit);
        ButterKnife.bind(this);

        sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    }

    @OnClick({R.id.bt_back, R.id.bt_submit})
    public void submit(View view) {

        switch (view.getId()) {
            case R.id.bt_back:
                _intent = new Intent(SubmitActivity.this, MainActivity.class);
                startActivity(_intent);
                this.finish();
                break;

            case R.id.bt_submit:
                User _user = new User();
                _user.setUserName(etName.getText().toString());
                _user.setUserAddress(sDateFormat.format(new java.util.Date()));
                MainActivity.mDBOperation.insertUser(_user);

                _intent = new Intent(SubmitActivity.this, MainActivity.class);
                startActivity(_intent);
                this.finish();
                break;

            default:
                break;
        }
    }
}

9、效果图演示

Android进阶之数据库存储_第1张图片

Android进阶之数据库存储_第2张图片

Android进阶之数据库存储_第3张图片

三、数据存储的最佳实现

使用事务,SQLite数据库是支持事务的,事务的特性可以保证让某一系列的操 作要么全部完成,要么一个都不会完成。例如:保证银行转账扣钱和收款的操作要么一起成功,要么都不会成功。

1、activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

<Button  android:id="@+id/replace_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Replace data" />
</LinearLayout> 

2、MainActivity.java

public class MainActivity extends Activity {

    private MyDatabaseHelper dbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        Button replaceData = (Button) findViewById(R.id.replace_data);
        replaceData.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.beginTransaction();
                // 开启事务
                try {
                    db.delete("Book", null, null);
                    if (true) {
                        // 在这里手动抛出一个异常,让事务失败
                        throw new NullPointerException();
                    }
                    ContentValues values = new ContentValues();
                    values.put("name", "Game of Thrones");
                    values.put("author", "George Martin");
                    values.put("pages", 720);
                    values.put("price", 20.85);
                    db.insert("Book", null, values);
                    db.setTransactionSuccessful();
                    // 事务已经执行成功
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    db.endTransaction();
                    // 结束事务
                }
            }
        });
    }
}

你可能感兴趣的:(数据库)