最近因为公司的项目需要操控到数据库,本来打算采用realm数据库,可是想想又懒了,还要集成那么多,于是还是采用sqlite数据库,毕竟用过那么多次了,但是一开始写,觉得很麻烦,又要写增删改查,从头写起,于是就打算封装一下,然后以后每个项目都可以直接拿来用,说起就干。
因为楼主最近在学后台,有接触到后台的框架,觉得特别方便,一个model扔进去,就可以映射成表,于是开始看了下这些框架的做法,最后采用注解+反射来写,虽然反射性能差,但是偶尔还是能用用的。
分解起来感觉只有这三步嘛,这里我们还没考虑注解映射成表,现在只是单纯的存取数据而已。
例如我们现在有一个User这个model
/**
* author: smart
* time: 2016/12/14
*/
public class User implements Serializable {
private int id;
private String name;
private int old;
private boolean sex;
private float number;
private double price;
private long count;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getOld() {
return old;
}
public void setOld(int old) {
this.old = old;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public float getNumber() {
return number;
}
public void setNumber(float number) {
this.number = number;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", old=" + old +
", sex=" + sex +
", number=" + number +
", price=" + price +
", count=" + count +
'}';
}
}
我们需要将一个User的实例转换为一个ContentValues,以便我们存储在数据库中,我们采用反射来获取User实例的各个属性值。
/**
* 解析数据得到ContentValues
* @param object
* @return
*/
public ContentValues getContentValues(Object object){
final ContentValues cv = new ContentValues();
Class c = object.getClass();
Field[] fields = c.getDeclaredFields();
Method[] methods = c.getDeclaredMethods();
for(Field field : fields) {
final String fieldName = field.getName();
String typeName = field.getType().getSimpleName();
String getMethodName;
if (typeName.equalsIgnoreCase("boolean")) {
getMethodName = "is" + fieldName;
} else {
getMethodName = "get" + fieldName;
}
//找到对应的get方法
Method method = getMethod(getMethodName, methods);
//获取方法返回值得类型
if (null != method) {
String className = method.getReturnType().getSimpleName();
try {
Object o = method.invoke(object);
getResult(className, o, new ValueTypeInterface() {
@Override
public void getValue(Integer result) {
cv.put(fieldName, result);
}
@Override
public void getValue(Boolean result) {
cv.put(fieldName, result);
}
@Override
public void getValue(Float result) {
cv.put(fieldName, result);
}
@Override
public void getValue(Double result) {
cv.put(fieldName, result);
}
@Override
public void getValue(Long result) {
cv.put(fieldName, result);
}
@Override
public void getValue(String result) {
cv.put(fieldName, result);
}
@Override
public void getValue(Byte result) {
cv.put(fieldName, result);
}
});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
return cv;
}
回调ValueTypeInterface主要作用是将Object对象转换中具体类型的对象。
当进行到这一步的时候,我们User的实例已经能映射成为一个ContentValues对象了,这个对象可以直接被插入数据库中,我们编写database数据库的操作方法,数据库的操作方式有哪些呢?不外乎,数据库的打开,关闭,增删改查。
/**
* author: smart
* time: 2016/12/15
*/
public interface DBAction {
void open(String dbName,String[] createTable,String[] updateTavleName,int version);
void close();
long insert(String tableName,T t);
long delete(String tableName, String[] whereClause, String[] whereArgs);
long update(String tableNamele, T t, String[] whereClause, String[] whereArgs);
List query(String tableNamele, String[] selection, String[] selectionArgs ,String orderBy,Class classZ);
}
数据库的操作我们定义好了,具体操作我们事先这个操作接口,其中我们的insert操作代码如下
@Override
public long insert(String tableName, T t) {
ContentValues cv = new ContentValues();
cv = dbUtils.getContentValues(t);
return db.insert(tableName,null,cv);
}
然后我们为每个Dao编写一个通用RootDao
/**
* author: smart
* time: 2016/12/15
*/
interface RootDao<T, PK extends Serializable> {
T get(PK id);
List findAll();
PK save(T entity);
void update(T entity);
void delete(PK id);
}
每个Dao的操作通用操作我们定义好了,现在我们编写UserDao专门操作User
/**
* author: smart
* time: 2016/12/15
*/
public interface UserDao extends RootDao<User,String> {
}
然后实现我们的UserDao,其中里面的save操作为
@Override
public String save(User entity) {
daoHelp.open();
Long a = daoHelp.getDao().insert(USERTABLE,entity);
daoHelp.close();
return String.valueOf(a);
}
例子比较随便,但还是能体现出来的,USERTABLE是我们的表名,其实到这一步,我们已经实现了model通过反射存入数据库中了,调用方式
findViewById(R.id.btnInsert).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
User user = new User();
user.setName("jredthree");
user.setOld(13);
user.setSex(true);
user.setNumber(123);
user.setPrice(333.4);
user.setCount(100000);
dao.save(user);
}
}
);
这里我们实现了存储,主要吸收了后台的一些知识,他山之石可以攻玉,多阅读优秀源码,可以成长的更快。
源码已上传github
github地址:https://github.com/jredthree/DBTest