1简介
安卓里常用的存储有方法中少不了数据库的使用,主要是对单表的操作,多表的操作此处不涉及。
每次使用数据库都会有繁琐的代码要写,大致思路是继承自SQLiteOpenHelper写一个数据库操作子类,然后重写onCreate方法,写上数据库的建表语句,重写onUpgrade方法,写上数据库的升级执行代码,此外还有繁琐的 增、删、改、查语句。每次建一张表都要做这些重复的工作,能不能用一种通用的方法,把这些繁琐的事务交给程序自动去完成呢?
下面的代码将告诉你答案。
ps:在我之前的博客里也用到了通过反射创建数据库表,操作数据库表的方法,方法虽然巧妙,但是之前的代码耦合度太高,只能是对具体案例使用,后来学习了Java泛型知识,可以通过泛型来传递对象类型的方法来降低耦合度,为了让自已的方法适用范围更广泛,所以整理于此。
我的源文章http://blog.csdn.net/u012990509/article/details/53838891点击打开链接
2使用到的知识
AJava反射
BJava泛型
C数据库知识(事务,基本语句)
3怎么用
先建立一个需要存储数据的实体类(要注意:类名,对象命名不能使用数据库专有字段(如date)否则会出现语句错误)
User.java
public class User {
//类名,对象命名要注意不能使用数据库专有字段
public int age;
public String name;
public boolean sex;
public User() {
}
public User(int age, String name, boolean sex) {
super();
this.age = age;
this.name = name;
this.sex = sex;
}
}
调用方法
//创建一张User表,字段名为user表的的公有变量名,通过改变实体类型可以建立不同的表
DBHelper<User> dbHelper = DBHelper.createDBHelper(this, User.class);
// 删除全部数据
dbHelper.delete(null, null);
// 插入单条
dbHelper.insert(new User(12, "aa", true));
dbHelper.insert(new User(13, "aaffd", true));
dbHelper.insert(new User(15, "fff", false));
dbHelper.insert(new User(16, "ggggg", true));
// 查询全部
Object object = dbHelper.querry();
System.out.println(JSON.toJSONString(object));
// 删除age=12的条目
dbHelper.delete("age=?", new String[] { "12" });
object = dbHelper.querry();
System.out.println(JSON.toJSONString(object));
// 查询age=13的条目
object = dbHelper.querry("age=?", new String[] { "13" });
System.out.println(JSON.toJSONString(object));
日志截图
A为查询全部数据
B为删除age=12后的全部数据
C为只查询单条age=13的数据
4真相在这里
DBHelper.java
package com.example.dbtest;
/**
* Created by liugd on 2016/12/23.
*/
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* 比分数据库
*
* @author liugd
*/
public class DBHelper<T> extends SQLiteOpenHelper {
private final static int DATABASE_VERSION = 1; // 数据库版本
private final static String DATABASE_NAME = "mydata.db";// 数据库名
private final String TABLE_NAME;// 表名
private DBHelperTool helperTool;
private Class<T> clazz;
public DBHelper(Context context, Class<T> clazz) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.TABLE_NAME = clazz.getSimpleName();
this.clazz = clazz;
this.helperTool = new DBHelperTool(clazz);
}
public static <T> DBHelper<T> createDBHelper(Context context, Class<T> clazz) {
return new DBHelper<T>(context, clazz);
}
@Override
public void onCreate(SQLiteDatabase db) {// 创建表
helperTool.onCreate(db, TABLE_NAME);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);// 重新创建表
}
// /插入数据
/****
* 更新数据
*
* @param item
* 更新的实体对象
*/
public synchronized int update(T item, String whereClause, String[] whereArgs) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction(); // 手动设置开始事务
int i = db.update(TABLE_NAME, helperTool.object2ContentValues(item), whereClause, whereArgs);
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
db.endTransaction(); // 处理完成
db.close();
return i;
// LogUitls.PrintObject("数据库", "更新单条数据" + (i == 1));
}
/***
* 插入所有数据
*
* @param list
* 需要插入的数据
*/
public synchronized long insert(T item) {
long count = 0;
try {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction(); // 手动设置开始事务
count = db.insert(TABLE_NAME, null, helperTool.object2ContentValues(item));
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
db.endTransaction(); // 处理完成
db.close();
} catch (Exception e) {
// LogUitls.PrintObject("数据库", e + "");
}
return count;
// LogUitls.PrintObject("数据库", "插入所有数据" + count);// 插入多少条数据
}
/***
* 插入所有数据
*
* @param list
* 需要插入的数据
*/
public synchronized long insert(List<T> list) {
long count = 0;
try {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction(); // 手动设置开始事务
for (Object item : list) {// 把数据复制一到一个新的集合里面
count += db.insert(TABLE_NAME, null, helperTool.object2ContentValues(item));
}
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
db.endTransaction(); // 处理完成
db.close();
} catch (Exception e) {
// LogUitls.PrintObject("数据库", e + "");
}
return count;
// LogUitls.PrintObject("数据库", "插入所有数据" + count);// 插入多少条数据
}
// //
// 删除数据
// /
/**
* 删除指定表的数据
*
* @return
*/
public synchronized boolean delete(String whereClause, String[] whereArgs) {
// LogUitls.PrintObject("数据库", " 删除所有数据");
int num = 0;
try {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction(); // 手动设置开始事务
num = db.delete(TABLE_NAME, whereClause, whereArgs);
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
db.endTransaction(); // 处理完成
db.close();
} catch (Exception e) {
// LogUitls.PrintObject("数据库", e + "");
System.out.println(e + "");
}
return num >= 1;
}
// //
// 查询数据
// /
// 查询单条数据
public T querrySingle() {
return querrySingle(null, null, null, null, null);
}
public T querrySingle(String selection, String[] selectioinArgs) {
return querrySingle(selection, selectioinArgs, null, null, null);
}
public T querrySingle(String selection, String[] selectioinArgs, String orderBy) {
return querrySingle(selection, selectioinArgs, null, null, orderBy);
}
/***
* 查询单条数据
*
* @return
*/
public synchronized T querrySingle(String selection, String[] selectioinArgs, String groupBy, String having, String orderBy) {
T ball = null;
try {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction(); // 手动设置开始事务
Cursor cursor = db.query(TABLE_NAME, helperTool.getStringFields(), selection, selectioinArgs, groupBy, having, orderBy);
if (cursor.moveToNext()) {
ball = clazz.newInstance();
helperTool.setObjectData(ball, cursor);
}
cursor.close();
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
db.endTransaction(); // 处理完成
db.close();
} catch (Exception e) {
// LogUitls.PrintObject("数据库", e + "");
}
return ball;
}
// 查询多条数据
public List<T> querry() {
return querry(null, null, null, null, null);
}
public List<T> querry(String selection, String[] selectioinArgs) {
return querry(selection, selectioinArgs, null, null, null);
}
public List<T> querry(String selection, String[] selectioinArgs, String orderBy) {
return querry(selection, selectioinArgs, null, null, orderBy);
}
/***
* 查询数据
*
* @return
*/
public synchronized List<T> querry(String selection, String[] selectioinArgs, String groupBy, String having, String orderBy) {
List<T> list = new ArrayList<T>();
try {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction(); // 手动设置开始事务
Cursor cursor = db.query(TABLE_NAME, helperTool.getStringFields(), selection, selectioinArgs, groupBy, having, orderBy);
while (cursor.moveToNext()) {
T ball = clazz.newInstance();
helperTool.setObjectData(ball, cursor);
list.add(ball);
}
cursor.close();
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
db.endTransaction(); // 处理完成
db.close();
} catch (Exception e) {
// LogUitls.PrintObject("数据库", e + "");
}
return list;
}
}
DBHelperTool.java
package com.example.dbtest;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.alibaba.fastjson.JSON;
/**
* 数据库处理助手,这里和业务逻辑无关是一个通用工具类 Created by liugd on 2016/12/22.
*/
public class DBHelperTool<T> {
private String[] stringFields = null;// 自动生成的,对象的字段名字
private Field[] flds = null;// 自动生成的实体类的的字段属性
public DBHelperTool(Class<T> clazz) {
initAllDatas(clazz);
}
/***
* 初始化所有的字段
*
* @param clazz
* 实体类
*/
private void initAllDatas(Class<T> clazz) {
Field[] tmp = clazz.getFields();// 得到有的公有字段,不需要创建表的字段请设置为实体类的私有字段
ArrayList<Field> list = new ArrayList<Field>(tmp.length);
for (int i = 0; i < tmp.length; i++) {
// 不取静态变量,当对象序列化时存在
if (!Modifier.isStatic(tmp[i].getModifiers())) {
list.add(tmp[i]);
}
}
flds = new Field[list.size()];
stringFields = new String[flds.length];
for (int i = 0; i < flds.length; i++) {
Field field = list.get(i);
flds[i] = field;
stringFields[i] = field.getName();// 得到字段的名字
}
}
/***
* 创建数据表
*
* @param db
* 数据库
* @param TABLE_NAME
* 表单
*/
public void onCreate(SQLiteDatabase db, String TABLE_NAME) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("(");
for (Field field : flds) {
Class<?> clazz = field.getType();// 得到字段的类型Intger、String、Boolean、Long
// 加入字段
stringBuilder.append(field.getName());// 得到字段的名字
// 判断 类型
if (clazz == String.class) {
stringBuilder.append(" nvarchar default \"\",");
} else if (clazz == int.class || clazz == boolean.class || clazz == long.class) {
stringBuilder.append(" INTEGER default 0,");
}
}
// 去掉最后一个逗号
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
stringBuilder.append(")");
// 创建三张表
String sql = "CREATE TABLE " + TABLE_NAME + stringBuilder.substring(0);
db.execSQL(sql);
System.out.println("创建表" + sql);
}
/***
* 设置对象的数据,通过映射设置数据
*
* @param ball
* 数据对象
* @param cursor
* 游标
*/
public void setObjectData(T item, Cursor cursor) {
for (int i = 0; i < flds.length; i++) {
try {
Class<?> clazz = flds[i].getType();
if (clazz == int.class) { // 判断类型
flds[i].set(item, cursor.getInt(i));
} else if (clazz == String.class) {
flds[i].set(item, cursor.getString(i));
} else if (clazz == boolean.class) {
flds[i].set(item, cursor.getInt(i) == 1 ? true : false);
} else if (clazz == long.class) {
flds[i].set(item, cursor.getLong(i));
}
} catch (Exception e) {
// LogUitls.PrintObject("数据库", "查询数据时取值映射出现问题" + e);
}
}
}
/**
* 得到对象所有的数据存入键值对
*
* @param item
* 条目数据
* @return 键值对 数据
*/
public ContentValues object2ContentValues(T item) {
ContentValues values = new ContentValues();
try {
for (int i = 0; i < flds.length; i++) {
String nameString = stringFields[i];// 得到字段名字
Object object = flds[i].get(item);
Class<?> clazz = flds[i].getType();
if (clazz == int.class) { // 判断类型
values.put(nameString, (Integer) object);
} else if (clazz == String.class) {
values.put(nameString, (String) object);
} else if (clazz == boolean.class) {
values.put(nameString, (Boolean) object ? 1 : 0);// 真为1,假为0
} else if (clazz == long.class) {
values.put(nameString, (Long) object);
}
}
} catch (Exception e) {
// LogUitls.PrintObject("数据库", "取值映射出现问题" + e);
}
return values;// 返回键值对
}
// GET SET METHOD
public Field[] getFlds() {
return flds;
}
public void setFlds(Field[] flds) {
this.flds = flds;
}
public String[] getStringFields() {
return stringFields;
}
public void setStringFields(String[] stringFields) {
this.stringFields = stringFields;
}
}
2017.3.12
如有疑问欢迎讨论
http://download.csdn.net/detail/u012990509/9778252点击打开链接 (下载的文件里面的版本非最新的,存在一个bug,DBHelperTool.java文件请以本文为准)