Android项目:SQLite编程之数据库的增删改查操作(基础篇)

实现功能:

1. 创建一个SQLiteOpenHelper子类

(1)实现数据库创建功能;

(2)实现升级管理功能;

2. 实现数据库的增删改查操作

(1)上方控件中输入数值,点击添加,则将数据存入数据库中,同时下方的ListView添加一行;

(2)点击下方的一行,则该行内容显示到上方的的控件中,修改其内容,然后点击修改按钮,则更新数据库和ListView;

(3)先用(2)中操作选择一行,然后点击删除按钮,则从数据库和界面中删除选中的数据;

(4)上方输入年龄值,点击查询按钮,则将大于等于该年龄值的查询结果(可能多行)用AlertDialog显示出来。例如:输入18,则显示:

 4 ccc 18 1.78

 5 ddd 19 1.8

1.activity_main.xml




    

    

    

    

    

    

    

    

    

    

    

    

2.items.xml




    

        

        

        

        
    

3.People.java

package com.example.sqlite;

public class People {
    public int ID = -1;
    public String Name;
    public int Age;
    public float Height;

    public int getID() {
        return ID;
    }

    public void setID(int ID) {
        this.ID = ID;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public int getAge() {
        return Age;
    }

    public void setAge(int age) {
        Age = age;
    }

    public float getHeight() {
        return Height;
    }

    public void setHeight(float height) {
        Height = height;
    }
}

4.MyDBOpenHelper.java

package com.example.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDBOpenHelper extends SQLiteOpenHelper {

    //必须重写的构造函数
    public MyDBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
                          int version) {
        super(context, name, factory, version);
    }

    //必须重写的创建数据库处理--传入的参数是框架中创建的SQLiteDatabase操作对象
    @Override
    public void onCreate(SQLiteDatabase db) {
        String createSQL="create table "+DBAdapter.DB_TABLE+" ("+DBAdapter.KEY_ID+
                " integer primary key autoincrement,"
                +DBAdapter.KEY_NAME+" text not null,"+DBAdapter.KEY_AGE+" integer,"+
                DBAdapter.KEY_HEIGHT+" float);";
        db.execSQL(createSQL); //执行创建语句
    }

    /*必须重写的升级数据库处理--准确的说,应该是版本变化处理:
            * 只要前面的构造函数中的版本不同于数据库文件的版本,就会调用此函数*/
    //三个参数: 数据库对象,旧版本号,新版本号
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS "+DBAdapter.DB_TABLE); //一般情况下不能直接删除数据,先保存...
        onCreate(db);
        System.out.println(oldVersion+"--"+newVersion);
    }

    //可选的方法---每次成功打开数据库后首先被执行
    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
    }
}

5.DBAdapter.java

package com.example.sqlite;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DBAdapter {
    //数据库基本信息
    private static final String DB_NAME="people.db";   //数据库名
    public static final String DB_TABLE="info";  //表名
    private static final int   DB_VERSION=1;	  //数据库版本
    //字段名称
    public static  final  String KEY_ID="id";
    public static  final  String KEY_NAME="name";
    public static  final  String KEY_AGE="age";
    public static  final  String KEY_HEIGHT="height";

    private SQLiteDatabase db=null;  //数据库对象
    private Context context; //记住由构造函数传入的上下文对象

    //数据库辅助操作对象
    private MyDBOpenHelper helper;

    public DBAdapter(Context context){
        this.context=context;  //记住由构造函数传入的上下文对象
        //若此处的数据库版本不同于系统文件中实际的版本,则会触发升级动作
        helper=new MyDBOpenHelper(context, DB_NAME, null, DB_VERSION);
    }

    //创建/打开数据库
    public boolean createDB(){
        try{
            db=helper.getWritableDatabase();
        }catch(Exception e){
            return false;
        }
        return true;
    }

    //添加
    public boolean insert(People people){
        ContentValues cv=new ContentValues();

        //设置插入的字段数值----对于自增的字段不需要设置
        cv.put(KEY_NAME, people.Name);
        cv.put(KEY_AGE, people.Age);
        cv.put(KEY_HEIGHT, people.Height);
        if (db.insert(DB_TABLE, null, cv)==-1)
            return false;

        return true;
    }

    //查询数据
    public List> query(){
        List> list = new ArrayList<>(); //结果列表

        //查询---可以使用占位符--SQL中的?对应后面字符串数组中的字符串,此处不用,第3个参数设置为null
        Cursor cursor=db.query(DB_TABLE,new String[]{KEY_ID,KEY_NAME,KEY_AGE,KEY_HEIGHT},
                null,null,null,null,null); //如果要查询的表不存在则会产生异常
        if (cursor.getCount()!=0){//查询结果不为空则依次查询并取值
            while (cursor.moveToNext()){ //循环取出游标中的查询结果
                //取出本行各列的值
                @SuppressLint("Range") int id=cursor.getInt(cursor.getColumnIndex(KEY_ID));
                @SuppressLint("Range") String name=cursor.getString(cursor.getColumnIndex(KEY_NAME));
                @SuppressLint("Range") int age=cursor.getInt(cursor.getColumnIndex(KEY_AGE));
                @SuppressLint("Range") float height=cursor.getFloat(cursor.getColumnIndex(KEY_HEIGHT));
                //写存入结果列表中
                Map map = new HashMap();
                map.put("id",id);
                map.put("name",name);
                map.put("age",age);
                map.put("height",height);
                list.add(map);
            } //继续取下一行
        }

        cursor.close(); //关闭游标

        return list;
    }

    //修改
    public long updateData(long id,People people){
        ContentValues cv=new ContentValues();

        cv.put(KEY_NAME, people.Name);
        cv.put(KEY_AGE, people.Age);
        cv.put(KEY_HEIGHT, people.Height);

        return db.update(DB_TABLE,cv,KEY_ID+"="+id,null);
    }

    //按id删除
    public long delete(long id){
        return db.delete(DB_TABLE, KEY_ID+"="+id,null);
    }

    //删除全部数据
    public long delete(){
        return db.delete(DB_TABLE, null,null);
    }

    //条件查询
    public People[] getData(long age){
        Cursor results = db.query(DB_TABLE,new String[]{KEY_ID,KEY_NAME,KEY_AGE,KEY_HEIGHT},
                KEY_AGE+">="+age,null,null,null,null);
        return ConvertToPeople(results);
    }

    @SuppressLint("Range")
    private People[] ConvertToPeople(Cursor cursor){
        //获取数据的条数
        int resultCounts = cursor.getCount();
        //如果没有数据,则返回null
        if (resultCounts == 0 || !cursor.moveToFirst())
                return null;
        //定义元素类型为People的列表对象,共有resultCounts个元素
        People[] peoples = new People[resultCounts];
        //将获得的数据逐条赋值给每个People对象peoples[i]
        for(int i = 0;i < resultCounts; i++){
            peoples[i] = new People();
            peoples[i].ID = cursor.getInt(0);
            peoples[i].Name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
            peoples[i].Age = cursor.getInt(cursor.getColumnIndex(KEY_AGE));
            peoples[i].Height = cursor.getFloat(cursor.getColumnIndex(KEY_HEIGHT));
            //将指针移到下一条数据
            cursor.moveToNext();
        }
        return peoples;
    }

    //关闭数据库对象
    public void close(){
        if (db!=null){
            db.close();
            db=null;
        }
    }

    //完成事务
    public  void execTransaction(boolean rollback){
        db.beginTransaction();  //开始事务
        delete(); //全部删除数据
        if (!rollback) //模拟检测条件,如果不回滚则设置事务完成,在结束事务时会正确提交
            db.setTransactionSuccessful(); //如不执行此项,则在结束事务时会回滚事务
        db.endTransaction(); //结束事务
    }

}

6.MainActivity.java

package com.example.sqlite;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends ListActivity {
    //数据库适配对象,用于操作数据库
    DBAdapter db=null;

    //Listview底层数据对象变量
    private List> list;

    //input输入框控件
    private TextView Name;
    private TextView Age;
    private TextView Height;

    //被点击的那行数据的id
    int reop_id = -1;

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

        //创建数据库适配对象
        db=new DBAdapter(this);
        //创建数据库
        if (!db.createDB()){
            Toast.makeText(MainActivity.this, "创建数据库失败!", Toast.LENGTH_SHORT).show();
            return;
        }

        //获取数据
        list=db.query();
        //创建自定义的Adapter对象
        MyAdapter adapter = new MyAdapter(this);
        setListAdapter(adapter);

        Button btnInsert = findViewById(R.id.insert);
        Button btnUpdate = findViewById(R.id.update);
        Button btnDelete = findViewById(R.id.delete);
        Button btnQuery = findViewById(R.id.query);

        Name = findViewById(R.id.name);
        Age = findViewById(R.id.age);
        Height = findViewById(R.id.height);

        //定义一个People类型的变量,用于存放一组信息
        People people = new People();

        //添加
        btnInsert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //将文本框控件中的信息赋值给people
                people.setName(Name.getText().toString());
                people.setAge(Integer.parseInt(Age.getText().toString()));
                people.setHeight(Float.parseFloat(Height.getText().toString()));
                db.insert(people);//将该组信息传参给insert函数-->将信息添加到数据库
                list = db.query();//获取此时数据库的所有信息,赋值给list-->用于显示在界面上
                //通知列表数据修改
                adapter.notifyDataSetChanged();
                //将上方控件中的内容清空
                Name.setText("");
                Age.setText("");
                Height.setText("");
            }
        });

        //修改
        btnUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                people.setName(Name.getText().toString());
                people.setAge(Integer.parseInt(Age.getText().toString()));
                people.setHeight(Float.parseFloat(Height.getText().toString()));
                db.updateData(reop_id,people);//更新被点击的那一行(指定id)的数据
                list = db.query();//获取此时数据库的所有信息,赋值给list-->用于显示在界面上
                //通知列表数据修改
                adapter.notifyDataSetChanged();
                //将上方控件中的内容清空
                Name.setText("");
                Age.setText("");
                Height.setText("");
            }
        });

        //删除
        btnDelete.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                db.delete(reop_id);//删除被点击的那一行(指定id)的数据
                list = db.query();//获取此时数据库的所有信息,赋值给list-->用于显示在界面上
                //通知列表数据修改
                adapter.notifyDataSetChanged();
                //将上方控件中的内容清空
                Name.setText("");
                Age.setText("");
                Height.setText("");
            }
        });

        //条件查询
        btnQuery.setOnClickListener(new View.OnClickListener() {
            int age;
            @Override
            public void onClick(View view) {
                //获取文本框中输入的年龄
                age = Integer.parseInt(Age.getText().toString());
                //获取条件查询得到的数据组
                People[] queryList = db.getData(age);
                if(queryList.length > 0){ //判断是否有符合条件的数据组
                    list.clear(); //如果有,则先清空此时显示在界面上的数据信息
                    //依次取出条件查询得到的数据组,并添加到list中-->用于显示在界面上
                    for(int i = 0; i < queryList.length; i++){
                        //用于获取一组数据的各字段信息,并存放在queryMap中
                        Map queryMap = new HashMap();
                        queryMap.put("id",queryList[i].ID);
                        queryMap.put("name",queryList[i].Name);
                        queryMap.put("age",queryList[i].Age);
                        queryMap.put("height",queryList[i].Height);
                        list.add(queryMap);
                    }
                }
                //通知列表数据修改
                adapter.notifyDataSetChanged();
                //将上方控件中的内容清空
                Name.setText("");
                Age.setText("");
                Height.setText("");
            }
        });

    }

    //定义静态的viewHolder类
    static class ViewHolder{
        TextView idOut;
        TextView nameOut;
        TextView ageOut;
        TextView heightOut;
    }

    public final class MyAdapter extends BaseAdapter{
        //实例化布局对象-->用来实例化每行的布局(View对象)
        private LayoutInflater mInflater;
        public MyAdapter(Context context){
            this.mInflater = LayoutInflater.from(context);
        }

        //获取List的总行数
        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Object getItem(int arg0) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertview, ViewGroup parent) {
            //定义viewHolder-->当listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能
            ViewHolder viewHolder;
            //当初始页面convertview缓存为空时,创建每一行的view
            if(convertview == null){
                viewHolder = new ViewHolder();
                //实例化一行的布局
                convertview = mInflater.inflate(R.layout.items,null);
                //找到行内子控件
                viewHolder.idOut=convertview.findViewById(R.id.idOutput);
                viewHolder.nameOut= convertview.findViewById(R.id.nameOutput);
                viewHolder.ageOut= convertview.findViewById(R.id.ageOutput);
                viewHolder.heightOut= convertview.findViewById(R.id.heightOutput);
                //将convertView的tag设置为viewHolder,
                convertview.setTag(viewHolder);
            }else{
                //当convertview不为空时,重复使用其中已有的view
                viewHolder = (ViewHolder) convertview.getTag();
            }

            //子控件赋值
            viewHolder.idOut.setText(String.valueOf((Integer)list.get(position).get("id")));
            viewHolder.nameOut.setText((String)list.get(position).get("name"));
            viewHolder.ageOut.setText(String.valueOf((Integer) list.get(position).get("age")));
            viewHolder.heightOut.setText(String.valueOf((Float)list.get(position).get("height")));

            //返回此时新的convertview缓存
            return convertview;
        }
    }

    //重写此方法——点击某一行时回调函数
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id){
        super.onListItemClick(l,v,position,id);

        reop_id = (Integer)list.get(position).get("id");
        //将该行内容显示到上方的的控件中
        Name.setText((String)list.get(position).get("name"));
        Age.setText(String.valueOf((Integer) list.get(position).get("age")));
        Height.setText(String.valueOf((Float)list.get(position).get("height")));
    }

    //退出界面,关闭数据库
    protected void onDestroy() {
        super.onDestroy();
        db.close();
    }

}

过程中遇到的问题及解决方法:

1)运行报错:android.content.res.Resources$NotFoundException: String resource ID #0x14
原因及解决方法:一般是指类型转换错误,比如不小心把int传给text.setText(),例子:text.setText(20);这是错误的,可以这样写text.setText(String.valueOf(20));

2)问题:在activity_main.xml中,ListView的布局失效
解决方法:因为ListView是相对父控件布局的,所以ListView要处在相对布局RelativeLayout下。

3)运行报错:Attempt to invoke virtual method 'android.view.View android.view.Window.findViewById(int)' on a null object reference
原因及解决方法:是因为想要获取的控件不在activity_main.xml里面,所以就会报空指针异常;应该先使用inflate获得另外的xml文件.再使用findViewById方法获取。
如:View account = View.inflate(this, R.layout.account, null);
navView = (NavigationView)account.findViewById(R.id.nav_view);

4)运行报错:java.lang.IllegalStateException: System services not available to Activities before onCreate()
原因及解决方法:此服务需要激活系统服务,所以要把此类变量的实例化工作放到MainActivity的OnCreate函数里面。

5)问题:每次查询时,之前在界面上的数据也还在
解决方法:查询前清空list列表

6)问题:查询时出现两条重复的数据,而其他符合条件的数据不显示(ArrayList.add后,前面数据被覆盖)
导致原因:
ArrayList集合里存的是同一个值,有可能是同一个引用或者就是同一个值。

错误代码:
ArrayList list = new ArrayList();
Object obj;
for (int i = 10; i > 0; i--) {
    obj = new Object();
    // obj = anotherObj;
    list.add(obj);
}

如错误代码所示,每次add的都是同一个引用,一个指向不同对象的引用obj
结果就是集合里所有的值都是obj,obj指向哪,集合里的值就指向哪。

解决方法:
将 Objec new在循环的里面。
for (int i = 10; i > 0; i--) {
  Object obj=new Object();
      objt.set(i);
      list.add(obj);
}

你可能感兴趣的:(笔记,sqlite,android,数据库)