安卓Android单表通用数据库、万能数据库的设计,(sqlite,java反射,泛型),使用非常方便

1简介

安卓里常用的存储有方法中少不了数据库的使用,主要是对单表的操作,多表的操作此处不涉及。

每次使用数据库都会有繁琐的代码要写,大致思路是继承自SQLiteOpenHelper写一个数据库操作子类,然后重写onCreate方法,写上数据库的建表语句,重写onUpgrade方法,写上数据库的升级执行代码,此外还有繁琐的 增、删、改、查语句。每次建一张表都要做这些重复的工作,能不能用一种通用的方法,把这些繁琐的事务交给程序自动去完成呢?

下面的代码将告诉你答案。

ps:在我之前的博客里也用到了通过反射创建数据库表,操作数据库表的方法,方法虽然巧妙,但是之前的代码耦合度太高,只能是对具体案例使用,后来学习了Java泛型知识,可以通过泛型来传递对象类型的方法来降低耦合度,为了让自已的方法适用范围更广泛,所以整理于此。

我的源文章http://blog.csdn.net/u012990509/article/details/53838891点击打开链接

2使用到的知识

AJava反射
BJava泛型
C数据库知识(事务,基本语句)

大体思路是利用泛型传递实体类的类型参数到数据库帮助类中,通过反射得到所有的类型字段,过滤,根据字段的类型(int、String、Long、Bool等)得到创建数据库的语句,select 查询时的全字段string数组,insert,update时的ContentValues,以及将查询后的结果转换成实体类等,具体见代码实现.

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文件请以本文为准)


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值