前些日子,搞了个Android项目,接触到了SQLite数据库
个人感觉有点麻烦:
1、数据库字段的修改,需要修改实体类,DAO类的字段的增加、修改、删除
2、传统的JDBC思想,体力劳动,十分浪费程序员的精力
3、程序耦合性太高,不够灵活
怎样才能将SQLite的DAO类使用的如同Hibernate一样简单呢?
Android的本身提供了SQLiteOpenHelper类、SQLiteDatabase类用作数据库方面的处理,很遗憾的是这两个类中没能提供如同Hibernate中Criteria类的操作
没办法,只能自己手工封装了,一切为了能有使用Hibernate的感觉
下面就给大家看代码了
首先定义一个BaseDAO的接口类,没太多的内容,就是实现类的方法汇总,这里呢就不提供了,让我们直接来看BaseDAO的实现类好了,尼玛,别说坑爹啊……
首先来看实现类的属性、构造函数、工具方法:
private DataBaseHelper helper;
private JavaBeanReflect reflect = JavaBeanReflect.getInstance();
private static Map<Class<? extends Object>, Class<? extends Object>> clsMap = new HashMap<Class<? extends Object>, Class<? extends Object>>();
static {
clsMap.put(int.class, Integer.class);
clsMap.put(long.class, Long.class);
clsMap.put(float.class, Float.class);
clsMap.put(double.class, Double.class);
clsMap.put(boolean.class, Boolean.class);
clsMap.put(byte.class, Byte.class);
clsMap.put(short.class, Short.class);
}
public SQLiteDAO(Context context) {
helper = new DataBaseHelper(context);
}
/**
* 获得更改数据库操作权限
* @return
*/
public SQLiteDatabase getWriteDataBase() {
return helper.getWritableDatabase();
}
/**
* 获得读取数据库操作权限
* @return
*/
public SQLiteDatabase getReadDataBase() {
return helper.getReadableDatabase();
}
/**
* 关闭数据库连接操作,释放资源
* @param db SQLiteDataBase对象
* @param cursor Cursor对象
*/
public void freeResource(SQLiteDatabase db, Cursor cursor) {
if (cursor != null) {
cursor.close();
}
if (db != null) {
db.close();
}
}
/**
* 将数据封装的ContentValues对象中
* 用于新增、更新数据操作
* @param t 实体类对象
* @return ContentValues对象
*/
public <T> ContentValues setAttribute(T t) {
ContentValues values = new ContentValues();
Field[] fields = reflect.getDeclaredFields(t.getClass());
for (Field field : fields) {
if (!"id".equals(field.getName())) {
values.put(field.getName(), String.valueOf(reflect.getFieldValue(t, field)));
}
}
return values;
}
/**
* 提取Cursor对象中的数据,并封装进实体类对象中
* @param cursor Cursor对象
* @param entity 实体类字节码
* @return 实体类对象
* @throws Exception
*/
public <T> T setAttribute(Cursor cursor, Class<T> entity) throws Exception {
if (cursor != null) {
Field[] fields = reflect.getDeclaredFields(entity);
String[] columns = cursor.getColumnNames();
T t = entity.newInstance();
for (Field field : fields) {
Class<? extends Object> cls = field.getType();
for (String column : columns) {
cls = getBasicClass(cls);
boolean isBool = isBasicType(cls);
if (isBool) {
if (column.equalsIgnoreCase(field.getName())) {
String str = cursor.getString(cursor.getColumnIndex(column));
if (str == null) {
break;
}
Constructor<? extends Object> con = cls.getConstructor(String.class);
Object obj = con.newInstance(str);
field.setAccessible(true);
field.set(t, obj);
}
} else {
Object obj = setAttribute(cursor, cls);
field.set(t, obj);
}
}
}
return t;
}
return null;
}
/**
* 获得包装类
* @param cls
* @return
*/
private Class<? extends Object> getBasicClass(Class<? extends Object> cls) {
Class<? extends Object> _cls = clsMap.get(cls);
if (_cls == null) {
_cls = cls;
}
return _cls;
}
/**
* 判断是否为基本类型
* @param cls
* @return
*/
private boolean isBasicType(Class<? extends Object> cls) {
if (Integer.class.equals(cls) || Long.class.equals(cls)
|| Float.class.equals(cls) || Double.class.equals(cls)
|| Boolean.class.equals(cls) || Byte.class.equals(cls)
|| Short.class.equals(cls) || String.class.equals(cls)) {
return true;
}
return false;
}
/**
* 将实体类属性字段封装到String数组中
* @param entity 实体类Class文件
* @return String[]数组
*/
public <T> String[] getColumns(Class<T> entity) {
Field[] fields = reflect.getDeclaredFields(entity);
String[] columns = new String[fields.length];
for (int i = 0; i < fields.length; i++) {
columns[i] = fields[i].getName();
}
return columns;
}
/**
* 封装SQL查询中的where子句
* @param paramNames where子句条件参数
* @return
*/
public String getSelection(String[] paramNames) {
if (paramNames.length > 0) {
StringBuilder builder = new StringBuilder();
for (String str : paramNames) {
builder.append(str + " = ? and ");
}
if (builder.length() > 0) {
builder.delete(builder.lastIndexOf("?") + 1, builder.length());
}
return builder.toString();
}
return null;
}
/**
* 封装SQL模糊查询中的where子句
* @param paramNames
* @return
*/
public String getBlurSelection(String[] paramNames) {
if (paramNames.length > 0) {
StringBuilder builder = new StringBuilder();
for (String str : paramNames) {
builder.append(str + " like ? and ");
}
if (builder.length() > 0) {
builder.delete(builder.lastIndexOf("?") + 1, builder.length());
}
return builder.toString();
}
return null;
}
public String[] getBlurValues(String[] values) {
String[] temps = new String[values.length];
for (int i = 0; i < values.length; i++) {
temps[i] = "%" + values[i] + "%";
}
return temps;
}
/**
* 获得分页查询条件
* @param start 分页开始位置
* @param max 分页显示数目
* @return
*/
public String getLimit(int start, int max) {
return start + "," + max;
}
/**
* 获得排序查询条件
* @param order 排序字段集合
* @return
*/
public String getOrder(Map<String, String> order) {
if (order != null) {
StringBuilder builder = new StringBuilder();
Set<String> keys = order.keySet();
for (String key : keys) {
String str = order.get(key);
if ("asc".equals(str) || "desc".equals(str)) {
builder.append(key + " " + str + ", ");
}
}
if (builder.length() > 0) {
builder.delete(builder.lastIndexOf(","), builder.length());
}
return builder.toString();
}
return null;
}
以上代码都有注释,也就不需要过多的解释了
不过有人会问JavaBeanReflect类代码有木有,贴在最后
下面是实现类实现的新增操作
@Override
public <T> long saveEntity(String tabName, T t) {
if (StringUtils.isEmpty(tabName)) {
return -1;
}
if (t == null) {
return -1;
}
ContentValues values = setAttribute(t);
SQLiteDatabase db = getWriteDataBase();
db.beginTransaction();
long id = db.insert(tabName, null, values);
db.setTransactionSuccessful();
db.endTransaction();
freeResource(db, null);
return id;
}
不好意思,这个没有注释,大家就凑合着看吧
删除操作
public <T> int deleteByID(String tabName, int id) {
if (StringUtils.isEmpty(tabName)) {
return -1;
}
String sql = "id = ?";
SQLiteDatabase db = getWriteDataBase();
db.beginTransaction();
int i = db.delete(tabName, sql, new String[] { String.valueOf(id) });
db.setTransactionSuccessful();
db.endTransaction();
freeResource(db, null);
return i;
}
修改操作
public <T> int updateEntity(String tabName, T t) {
if (StringUtils.isEmpty(tabName)) {
return -1;
}
ContentValues values = setAttribute(t);
String sql = "id = ?";
SQLiteDatabase db = getWriteDataBase();
db.beginTransaction();
int i = db.update(tabName, values, sql,
new String[] { String.valueOf(JavaBeanReflect.getInstance()
.getFieldValue(t, "id")) });
db.setTransactionSuccessful();
db.endTransaction();
freeResource(db, null);
return i;
}
根据ID查询操作
@Override
public <T> T findByID(String tabName, Class<T> entity, int id) {
if (StringUtils.isEmpty(tabName)) {
return null;
}
String[] columns = getColumns(entity);
String selection = "id = ?";
String[] values = new String[] { String.valueOf(id) };
SQLiteDatabase db = getReadDataBase();
Cursor cursor = db.query(tabName, columns, selection, values, null, null, null);
T t = null;
while (cursor.moveToNext()) {
try {
t = setAttribute(cursor, entity);
} catch (Exception e) {
e.printStackTrace();
}
}
freeResource(db, cursor);
return t;
}
查询所有数据集合(单张表)
public <T> List<T> findAll(String tabName, Class<T> entity) {
if (StringUtils.isEmpty(tabName)) {
return null;
}
String[] columns = getColumns(entity);
SQLiteDatabase db = getReadDataBase();
Cursor cursor = db.query(tabName, columns, null, null, null, null, null);
List<T> list = new ArrayList<T>();
while (cursor.moveToNext()) {
try {
T t = setAttribute(cursor, entity);
list.add(t);
} catch (Exception e) {
e.printStackTrace();
}
}
freeResource(db, cursor);
return list;
}
分页查询操作
public <T> List<T> findAll(String tabName, Class<T> entity, int start, int max) {
if (StringUtils.isEmpty(tabName)) {
return null;
}
String[] columns = getColumns(entity);
String limit = getLimit(start, max);
SQLiteDatabase db = getReadDataBase();
Cursor cursor = db.query(tabName, columns, null, null, null, null, null, limit);
List<T> list = new ArrayList<T>();
while (cursor.moveToNext()) {
try {
T t = setAttribute(cursor, entity);
list.add(t);
} catch (Exception e) {
e.printStackTrace();
}
}
freeResource(db, cursor);
return list;
}
排序查询操作
public <T> List<T> findAll(String tabName, Class<T> entity, Map<String, String> order) {
if (StringUtils.isEmpty(tabName)) {
return null;
}
String[] columns = getColumns(entity);
String orderBy = getOrder(order);
SQLiteDatabase db = getReadDataBase();
Cursor cursor = db.query(tabName, columns, null, null, null, null, orderBy);
List<T> list = new ArrayList<T>();
while (cursor.moveToNext()) {
try {
T t = setAttribute(cursor, entity);
list.add(t);
} catch (Exception e) {
e.printStackTrace();
}
}
freeResource(db, cursor);
return list;
}
分页、排序一起来的就不上代码了,上面两个结合一下就好了
条件查询操作:
public <T> List<T> findByPropery(String tabName, Class<T> entity, String[] paramNames, String[] values) {
if (StringUtils.isEmpty(tabName)) {
return null;
}
String[] columns = getColumns(entity);
String selection = getSelection(paramNames);
SQLiteDatabase db = getReadDataBase();
Cursor cursor = db.query(tabName, columns, selection, values, null, null, null);
List<T> list = new ArrayList<T>();
while (cursor.moveToNext()) {
try {
T t = setAttribute(cursor, entity);
list.add(t);
} catch (Exception e) {
e.printStackTrace();
}
}
freeResource(db, cursor);
return list;
}
模糊查询操作
public <T> List<T> findByBlur(String tabName, Class<T> entity, String[] paramNames, String[] values) {
if (StringUtils.isEmpty(tabName)) {
return null;
}
String[] columns = getColumns(entity);
String selection = getBlurSelection(paramNames);
values = getBlurValues(values);
SQLiteDatabase db = getReadDataBase();
Cursor cursor = db.query(tabName, columns, selection, values, null, null, null);
List<T> list = new ArrayList<T>();
while (cursor.moveToNext()) {
try {
T t = setAttribute(cursor, entity);
list.add(t);
} catch (Exception e) {
e.printStackTrace();
}
}
freeResource(db, cursor);
return list;
}
JavaBeanReflect类代码
/**
* 针对JavaBean操作的反射工具类
* @author Francis-ChinaFeng
* @version 1.0 2013-07-08
*/
public class JavaBeanReflect {
/**
* 单例模式
*/
private static JavaBeanReflect reflect = new JavaBeanReflect();
private JavaBeanReflect() { }
public static JavaBeanReflect getInstance() {
return reflect;
}
/**
* 获得实体类中的属性信息数组
* @param entity
* @return
*/
public <T> Field[] getDeclaredFields(Class<T> entity) {
return entity.getDeclaredFields();
}
/**
* 获得实体类中属性对应的值
* @param t
* @param field
* @return
*/
public <T> Object getFieldValue(T t, Field field) {
field.setAccessible(true);
Object obj = null;
try {
obj = field.get(t);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
field.setAccessible(false);
return obj;
}
/**
* 获得实体类中属性对应的值
* @param t
* @param fieldName
* @return
*/
public <T> Object getFieldValue(T t, String fieldName) {
try {
Field field = t.getClass().getDeclaredField(fieldName);
return getFieldValue(t, field);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return null;
}
}
虽然没有将代码全贴出来,不过也就那么几个方法
增加:新增实体类,批量增加
删除:根据ID删除、根据属性删除、模糊删除
更新:根据ID更新、根据属性更新、模糊更新
查询全部,代码全贴
根据属性查询:按照全部添加分页、排序操作
模糊查询同属性查询一样
这样,DAO实现类也就封装好了
如果在实际情况中的业务需求还需要其他复杂的操作,大家可以拓展下
Hibernate也可以使用该封装方法的思想
拍砖请联系QQ:920656263
希望对大家有所帮助~~ 谢谢
* 备注:
* 因为查询操作中使用的是反射的技术
* 故以封装好的程序暂时无法支持DATE数据类型
* 如果需求DATE数据类型
* 1、请重写setAttribute(Cursor cursor, Class<T> entity)方法,或者自定义操作方法
* 2、请使用System.currentTimeMillis()方法获取long类型的时间值,在业务层进行业务处理