Litepal 使用原生Sql进行复杂查询的反射工具类
问题:
这几天因为课程原因,开始是Android开发的学习,在学习本地持久化层框架Litepal时,赞叹它使数据库操作如此简单优雅,但是今天,本人在项目作业上有一个多条件组合的查询,就是类似 下面这样的组合条件
where
(senderNetId = ? AND receiverNetId = ?)
OR
(receiverNetId = ? AND senderNetId = ?)
order by createtime desc
limit 20
看了官方文档和一些博客,并没有找到直接可以用的方式,所以就只能用 Litepal 的 findBySql(”sql statement“),这个方法会返回一个 Cursor cursor 的对象,这个对象就是一个从数据库中查询出来的结果集,就好比是之前做Web开发,原生数据库JDBC操作,返回的结果集 ResultSet 是一回事。
首先就想到了能否做到对结果集进行通用的处理呢?结合数据库ORM这些框架,不管是 Litepal 还是Hibernate、Mybatis。反射,这是可以解决软件通用性的好东西,同时也是各种框架的很多底层技术的支撑。
这里,便想着通过反射,对数据集进行通用性的处理转成 List 形式,写一个工具类,开发人员不需要针对结果集进行重复性很大的编写工作。代码还有很多未完善优化的地方,仅提供一些思路。
用例:
public ArrayList<Message> findNearlyMessage(int friendNetId,int ownerNetId){
String fnId=String.valueOf(friendNetId);
String onId=String.valueOf(ownerNetId);
//Litepal 的 findBySQL 方法
Cursor cursor=
LitePal.findBySQL(
"select * from message
where
(senderNetId = ? AND receiverNetId = ?)
OR
(receiverNetId = ? AND senderNetId = ?)
order by createtime desc
limit 20",
onId,fnId,
fnId,onId);
//调用工具类对cursor进行提取数据封装处理
ArrayList<Message> messages=DBUtil.cursorToList(cursor,Message.class);
if (messages.size()==0||messages==null){
return new ArrayList<Message>();
}
return messages;
}
工具类 DBUtil 的 cursorToList 方法
public static ArrayList cursorToList(Cursor cursor,Class objClass) {
try {
ArrayList objList=new ArrayList();
//获取全部字段名
Field[] fields=objClass.getDeclaredFields();
//通过fieldName获取指定数据
while (cursor.moveToNext()){
Object newObj=objClass.newInstance();
for (Field field : fields){
field.setAccessible(true);
String colName=field.getName().toLowerCase();
Class fileType=field.getType();
int valueIndex=cursor.getColumnIndex(colName);
Object value=null;
//
//根据字段类型判断调用哪个方法/String/Int/Long/boolean
//这一块可以进行优化,做到更通用性
switch (fileType.getSimpleName()){
case "String":
value=cursor.getString(valueIndex);
break;
case "int":
value=cursor.getInt(valueIndex);
break;
case "long":
value=cursor.getLong(valueIndex);
break;
case "boolean":
int dbVal=cursor.getInt(valueIndex);
value=true;
if (dbVal == 0){
value=false;
}
}
field.set(newObj,value);
}
objList.add(newObj);
}
return objList;
}catch (Exception e){
e.printStackTrace();
return null;
}
}