接上一节 一起来写个SQLite ORM数据库框架(上) 这节讲下代码实现。
首先有4个注解类:表名注解-Table、主键注解-PrimaryKey、列注解-Column、非数据库字段注解-NotDBColumn。因为篇幅的原因 这里只单独看看新增的实现 其他都类似
列注解类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
String value() default "";
String defaultValue() default "";
}
列注解对应的对象实体类(ColumnEntity ):
public class ColumnEntity {
/**
* 实体类中的属性字段
*/
private Field field;
private String columnName;
private String defaultValue;
/**
* 获取指定对象的当前字段的值
* @param entity 获取字段值的对象
* @return
*/
public Object getValue(Object entity) {
if(entity != null) {
try {
//设置属性是可以访问的
field.setAccessible(true);
return field.get(entity);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 设置指定对象的当前字段的值
* @param entity 获取字段值的对象
* @return
*/
public void setValue(Object entity, Cursor cursor) throws Exception{
Class<?> fieldType = field.getType();
try {
int columnIdx = cursor.getColumnIndex(columnName);
if(columnIdx == -1) {//当前游标中没有该字段的值
return;
}
field.setAccessible(true);
if(fieldType==int.class||fieldType==Integer.class) {
field.set(entity, cursor.getInt(columnIdx));
return;
}
if(fieldType==char.class||fieldType==String.class){
field.set(entity, cursor.getString(columnIdx));
return;
}
if(fieldType==long.class||fieldType==Long.class){
field.set(entity, cursor.getLong(columnIdx));
return;
}
if(fieldType==float.class||fieldType==Float.class){
field.set(entity, cursor.getFloat(columnIdx));
return;
}
if(fieldType==double.class||fieldType==Double.class){
field.set(entity, cursor.getDouble(columnIdx));
return;
}
} catch (Exception e) {
throw e;
}
}
// public Field getField() {
// return field;
// }
public void setField(Field field) {
this.field = field;
}
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
}
解析注解映射对象管理类(TableEntityManager ):
public class TableEntityManager {
/**
* 每张表的相关信息缓存集合
*/
private static HashMap<Object, TableEntity> mTableMap = new HashMap<Object, TableEntity>();
/**
* 获取EntityTable对象
*/
public static <T> TableEntity getTableEntity(T entity) {
return getTableEntity(entity.getClass());
}
public static <T> TableEntity getTableEntity(Class<?> mClass) {
if(mTableMap.containsKey(mClass)) {
return mTableMap.get(mClass);
} else {
return createTableEntity(mClass);
}
}
public static TableEntity createTableEntity(Class<?> mClass) {
TableEntity tableEntity = new TableEntity();
//设置表名
setTableName(tableEntity,mClass);
//设置主键和列
setColumnList(tableEntity,mClass);
mTableMap.put(mClass, tableEntity);
return tableEntity;
}
/**
* 解析注解设置表名
*/
public static void setTableName(TableEntity tableEntity,Class<?> mClass) {
Table table = mClass.getAnnotation(Table.class);
if(null==table||TextUtils.isEmpty(table.value())) {
tableEntity.setTableName(mClass.getSimpleName());
}
tableEntity.setTableName(table.value());
}
/**
* 解析注解设置主键(PrimaryKeyEntity)
*/
public static boolean setPrimaryKey(TableEntity tableEntity,Field field){
PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class);
if(null == primaryKey) {
return false;
}
if(primaryKey.isAutoGenerate() && field.getType()!=long.class && field.getType()!=int.class){
throw new RuntimeException("自增长主键字段类型不正确,请设置自增长字段类型为long或者int");
}
PrimaryKeyEntity primaryKeyEntity = new PrimaryKeyEntity();
primaryKeyEntity.setField(field);
if(TextUtils.isEmpty(primaryKey.value())) {//没有通过注解设置列名,默认取字段名称为列名
primaryKeyEntity.setColumnName(field.getName());
} else {
primaryKeyEntity.setColumnName(primaryKey.value());
}
primaryKeyEntity.setAutoGenerate(primaryKey.isAutoGenerate());//获取是否自动增长
tableEntity.setPrimaryKey(primaryKeyEntity);
return true;
}
/**
* 解析注解获得字段列名和默认值并封装到 ColumnEntity
*/
public static void setColumnList(TableEntity tableEntity,Class<?> mClass) {
Field[] fields = mClass.getDeclaredFields();
List<ColumnEntity> columnList = new ArrayList<ColumnEntity>();
ColumnEntity columnEntity = null;
for(Field field:fields){
if (Modifier.isStatic(field.getModifiers())) {//过滤掉static静态字段
continue;
}
if(field.getType() == Object.class) {//过滤掉非基本类型字段
continue;
}
NotDBColumn notDbColumn = field.getAnnotation(NotDBColumn.class);
if(null != notDbColumn) {//非数据库字段不作处理
continue;
}
if(null==tableEntity.getPrimaryKey()){ //判断是否有主键注释 并设置主键
if(setPrimaryKey(tableEntity,field)){
continue;
}
}
//获取每个字段的注解
Column column = field.getAnnotation(Column.class);
columnEntity = new ColumnEntity();
columnEntity.setField(field);
// 解析注解设置列名,默认取字段名称为列名
String columnName = field.getName();
if(column != null) {
if (!TextUtils.isEmpty(column.value())) {
columnName = column.value();
}
if(!TextUtils.isEmpty(column.defaultValue())){
columnEntity.setDefaultValue(column.defaultValue());
}
}
columnEntity.setColumnName(columnName);
columnList.add(columnEntity);
}
tableEntity.setColumnList(columnList);
}
}
拼接SQL语句类(SQLBuilder) 这里说下在拼创建表的sql的时候 我并没有把字段类型拼上 这是由于对于sqllite数据库 它有个特点就是可以是无类型的 意思就是你给它什么类型 它就会存什么类型 所以我省去转化类型的步骤
//拼接插入的sql语句
public static <T> BindSQL getInsertSQL(TableEntity tableEntity,T entity){
StringBuilder sql = new StringBuilder();
StringBuilder valueSql = new StringBuilder();
int size = tableEntity.getColumnList().size();
Object[] args = new Object[size+1];
sql.append("INSERT INTO ").append(tableEntity.getTableName()).append("(");
valueSql.append(" VALUES(");
int i = 0;
PrimaryKeyEntity primaryKey = tableEntity.getPrimaryKey();
if(null!=primaryKey&&!primaryKey.isAutoGenerate()){
sql.append(primaryKey.getColumnName()+",");
valueSql.append("?,");
args[i++] = primaryKey.getValue(entity);
}
for (ColumnEntity columnEntity:tableEntity.getColumnList()){
Object valueObj = columnEntity.getValue(entity);
if(null!=valueObj){
sql.append(columnEntity.getColumnName());
sql.append(",");
valueSql.append("?");
valueSql.append(",");
args[i++] = columnEntity.getValue(entity);
}
}
sql.deleteCharAt(sql.length() - 1);
valueSql.deleteCharAt(valueSql.length()-1);
sql.append(")");
valueSql.append(")");
sql.append(valueSql);
Object[] args2 = new Object[i];
System.arraycopy(args,0,args2,0,i);
return new BindSQL(sql.toString(),args2);
};
执行数据库操作管理类(SQLExecuteManager ):
/**
* 新增一条数据
*/
public <T> long insert(T entity){
TableEntity tableEntity = TableEntityManager.getTableEntity(entity);
BindSQL bindSQL = SQLBuilder.getInsertSQL(tableEntity,entity);
long rowId = insert(bindSQL.getSql(),bindSQL.getBindArgs());
return rowId;
}
框架入口类(SQLiteDB)
/**
* 新增一条数据
*/
public <T> long insert(T entity){
return mSQLExecuteManager.insert(entity);
}
整个easyDB数据库框架的大体结构就介绍到这里了,大家可以下载源码查看更多实现 ,还有很多不足的地方 比如不支持多数据库,线程安全等 也可以自行扩展。