diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java b/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java index 0ebd9534..9b1ec3ab 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java @@ -1,634 +1,640 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.orm; - -import android.annotation.TargetApi; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.os.Build; -import android.text.TextUtils; -import com.arialyy.aria.orm.annotation.Many; -import com.arialyy.aria.orm.annotation.One; -import com.arialyy.aria.orm.annotation.Wrapper; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; -import com.arialyy.aria.util.CommonUtil; -import java.lang.reflect.Field; -import java.net.URLDecoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Created by laoyuyu on 2018/3/22. - * 查询数据 - */ -class DelegateFind extends AbsDelegate { - private final String PARENT_COLUMN_ALIAS = "p"; - private final String CHILD_COLUMN_ALIAS = "c"; - - private DelegateFind() { - } - - /** - * 获取{@link One}和{@link Many}注解的字段 - * - * @return 返回[OneField, ManyField] ,如果注解依赖错误返回null - */ - private Field[] getOneAndManyField(Class clazz) { - Field[] om = new Field[2]; - Field[] fields = clazz.getDeclaredFields(); - Field one = null, many = null; - boolean hasOne = false, hasMany = false; - for (Field field : fields) { - if (SqlUtil.isOne(field)) { - if (hasOne) { - ALog.w(TAG, "查询数据失败,实体中有多个@One 注解"); - return null; - } - hasOne = true; - one = field; - } - if (SqlUtil.isMany(field)) { - if (hasMany) { - ALog.w(TAG, "查询数据失败,实体中有多个@Many 注解"); - return null; - } - if (!field.getType().isAssignableFrom(List.class)) { - ALog.w(TAG, "查询数据失败,@Many 注解的类型不是List"); - return null; - } - hasMany = true; - many = field; - } - } - - if (one == null || many == null) { - ALog.w(TAG, "查询数据失败,实体中没有@One或@Many注解"); - return null; - } - - if (many.getType() != List.class) { - ALog.w(TAG, "查询数据失败,@Many注解的字段必须是List"); - return null; - } - om[0] = one; - om[1] = many; - return om; - } - - /** - * 查找一对多的关联数据 - * 如果查找不到数据或实体没有被{@link Wrapper}注解,将返回null - * 如果实体中没有{@link One}或{@link Many}注解,将返回null - * 如果实体中有多个{@link One}或{@link Many}注解,将返回nul - * {@link One} 的注解对象必须是{@link DbEntity},{@link Many}的注解对象必须是List,并且List中的类型必须是{@link DbEntity} - */ - List findRelationData(SQLiteDatabase db, Class clazz, - String... expression) { - return exeRelationSql(db, clazz, -1, -1, expression); - } - - /** - * 查找一对多的关联数据 - * 如果查找不到数据或实体没有被{@link Wrapper}注解,将返回null - * 如果实体中没有{@link One}或{@link Many}注解,将返回null - * 如果实体中有多个{@link One}或{@link Many}注解,将返回nul - * {@link One} 的注解对象必须是{@link DbEntity},{@link Many}的注解对象必须是List,并且List中的类型必须是{@link DbEntity} - */ - List findRelationData(SQLiteDatabase db, Class clazz, - int page, int num, String... expression) { - if (page < 1 || num < 1) { - return null; - } - return exeRelationSql(db, clazz, page, num, expression); - } - - /** - * 执行关联查询,如果不需要分页,page和num传-1 - * - * @param page 当前页 - * @param num 一页的数量 - */ - private List exeRelationSql(SQLiteDatabase db, Class clazz, - int page, int num, String... expression) { - db = checkDb(db); - if (SqlUtil.isWrapper(clazz)) { - Field[] om = getOneAndManyField(clazz); - if (om == null) { - return null; - } - StringBuilder sb = new StringBuilder(); - Field one = om[0], many = om[1]; - try { - Many m = many.getAnnotation(Many.class); - Class parentClazz = Class.forName(one.getType().getName()); - Class childClazz = Class.forName(CommonUtil.getListParamType(many).getName()); - final String pTableName = parentClazz.getSimpleName(); - final String cTableName = childClazz.getSimpleName(); - List pColumn = SqlUtil.getAllNotIgnoreField(parentClazz); - List cColumn = SqlUtil.getAllNotIgnoreField(childClazz); - List pColumnAlias = new ArrayList<>(); - List cColumnAlias = new ArrayList<>(); - StringBuilder pSb = new StringBuilder(); - StringBuilder cSb = new StringBuilder(); - - if (pColumn != null) { - pSb.append(pTableName.concat(".rowid AS ").concat(PARENT_COLUMN_ALIAS).concat("rowid,")); - for (Field f : pColumn) { - String temp = PARENT_COLUMN_ALIAS.concat(f.getName()); - pColumnAlias.add(temp); - pSb.append(pTableName.concat(".").concat(f.getName())) - .append(" AS ") - .append(temp) - .append(","); - } - } - - if (cColumn != null) { - pSb.append(cTableName.concat(".rowid AS ").concat(CHILD_COLUMN_ALIAS).concat("rowid,")); - for (Field f : cColumn) { - String temp = CHILD_COLUMN_ALIAS.concat(f.getName()); - cColumnAlias.add(temp); - cSb.append(cTableName.concat(".").concat(f.getName())) - .append(" AS ") - .append(temp) - .append(","); - } - } - - String pColumnAlia = pSb.toString(); - String cColumnAlia = cSb.toString(); - if (!TextUtils.isEmpty(pColumnAlia)) { - pColumnAlia = pColumnAlia.substring(0, pColumnAlia.length() - 1); - } - - if (!TextUtils.isEmpty(cColumnAlia)) { - cColumnAlia = cColumnAlia.substring(0, cColumnAlia.length() - 1); - } - - sb.append("SELECT "); - - if (!TextUtils.isEmpty(pColumnAlia)) { - sb.append(pColumnAlia).append(","); - } - if (!TextUtils.isEmpty(cColumnAlia)) { - sb.append(cColumnAlia); - } - if (TextUtils.isEmpty(pColumnAlia) && TextUtils.isEmpty(cColumnAlia)) { - sb.append(" * "); - } - - sb.append(" FROM ") - .append(pTableName) - .append(" INNER JOIN ") - .append(cTableName) - .append(" ON ") - .append(pTableName.concat(".").concat(m.parentColumn())) - .append(" = ") - .append(cTableName.concat(".").concat(m.entityColumn())); - String sql; - if (expression != null && expression.length > 0) { - CheckUtil.checkSqlExpression(expression); - sb.append(" WHERE ").append(expression[0]).append(" "); - sql = sb.toString(); - sql = sql.replace("?", "%s"); - Object[] params = new String[expression.length - 1]; - for (int i = 0, len = params.length; i < len; i++) { - params[i] = String.format("'%s'", encodeStr(expression[i + 1])); - } - sql = String.format(sql, params); - } else { - sql = sb.toString(); - } - if (page != -1 && num != -1) { - sql = sql.concat(String.format(" LIMIT %s,%s", (page - 1) * num, num)); - } - - print(RELATION, sql); - Cursor cursor = db.rawQuery(sql, null); - List data = - (List) newInstanceEntity(clazz, parentClazz, childClazz, cursor, pColumn, cColumn, - pColumnAlias, cColumnAlias); - closeCursor(cursor); - close(db); - return data; - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } else { - ALog.e(TAG, "查询数据失败,实体类没有使用@Wrapper 注解"); - return null; - } - return null; - } - - /** - * 创建关联查询的数据 - * - * @param pColumn 父表的所有字段 - * @param cColumn 字表的所有字段 - * @param pColumnAlias 关联查询父表别名 - * @param cColumnAlias 关联查询子表别名 - */ - private synchronized List newInstanceEntity( - Class clazz, Class

parent, - Class child, - Cursor cursor, - List pColumn, List cColumn, - List pColumnAlias, List cColumnAlias) { - try { - String parentPrimary = ""; //父表主键别名 - for (Field f : pColumn) { - if (SqlUtil.isPrimary(f)) { - parentPrimary = PARENT_COLUMN_ALIAS.concat(f.getName()); - break; - } - } - - List wrappers = new ArrayList<>(); - Map tempParent = new LinkedHashMap<>(); // 所有父表元素,key为父表主键的值 - Map> tempChild = new LinkedHashMap<>(); // 所有的字表元素,key为父表主键的值 - - Object old = null; - while (cursor.moveToNext()) { - //创建父实体 - Object ppValue = setPPValue(parentPrimary, cursor); - if (old == null || ppValue != old) { //当主键不同时,表示是不同的父表数据 - old = ppValue; - if (tempParent.get(old) == null) { - P pEntity = parent.newInstance(); - String pPrimaryName = ""; - for (int i = 0, len = pColumnAlias.size(); i < len; i++) { - Field pField = pColumn.get(i); - pField.setAccessible(true); - Class type = pField.getType(); - int column = cursor.getColumnIndex(pColumnAlias.get(i)); - if (column == -1) continue; - setFieldValue(type, pField, column, cursor, pEntity); - - if (SqlUtil.isPrimary(pField) && (type == int.class || type == Integer.class)) { - pPrimaryName = pField.getName(); - } - } - - //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 - pEntity.rowID = cursor.getInt( - cursor.getColumnIndex( - TextUtils.isEmpty(pPrimaryName) ? PARENT_COLUMN_ALIAS.concat("rowid") - : pPrimaryName)); - - tempParent.put(ppValue, pEntity); - } - } - - // 创建子实体 - C cEntity = child.newInstance(); - String cPrimaryName = ""; - for (int i = 0, len = cColumnAlias.size(); i < len; i++) { - Field cField = cColumn.get(i); - cField.setAccessible(true); - Class type = cField.getType(); - - int column = cursor.getColumnIndex(cColumnAlias.get(i)); - if (column == -1) continue; - setFieldValue(type, cField, column, cursor, cEntity); - - if (SqlUtil.isPrimary(cField) && (type == int.class || type == Integer.class)) { - cPrimaryName = cField.getName(); - } - } - //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 - cEntity.rowID = cursor.getInt( - cursor.getColumnIndex( - TextUtils.isEmpty(cPrimaryName) ? CHILD_COLUMN_ALIAS.concat("rowid") - : cPrimaryName)); - if (tempChild.get(old) == null) { - tempChild.put(old, new ArrayList()); - } - tempChild.get(old).add(cEntity); - } - - List wFields = SqlUtil.getAllNotIgnoreField(clazz); - if (wFields != null && !wFields.isEmpty()) { - Set pKeys = tempParent.keySet(); - for (Object pk : pKeys) { - T wrapper = clazz.newInstance(); - P p = tempParent.get(pk); - boolean isPSet = false, isCSet = false; - for (Field f : wFields) { - if (!isPSet && f.getAnnotation(One.class) != null) { - f.set(wrapper, p); - isPSet = true; - } - if (!isCSet && f.getAnnotation(Many.class) != null) { - f.set(wrapper, tempChild.get(pk)); - isCSet = true; - } - } - wrapper.handleConvert(); //处理下转换 - wrappers.add(wrapper); - } - } - return wrappers; - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - - /** - * 获取父表主键数据 - * - * @param parentPrimary 父表主键别名 - */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) private Object setPPValue(String parentPrimary, - Cursor cursor) { - Object ppValue = null; - int ppColumn = cursor.getColumnIndex(parentPrimary); //父表主键所在的列 - int type = cursor.getType(ppColumn); - switch (type) { - case Cursor.FIELD_TYPE_INTEGER: - ppValue = cursor.getLong(ppColumn); - break; - case Cursor.FIELD_TYPE_FLOAT: - ppValue = cursor.getFloat(ppColumn); - break; - case Cursor.FIELD_TYPE_STRING: - ppValue = cursor.getString(ppColumn); - break; - } - return ppValue; - } - - /** - * 条件查寻数据 - */ - List findData(SQLiteDatabase db, Class clazz, String... expression) { - db = checkDb(db); - CheckUtil.checkSqlExpression(expression); - String sql = String.format("SELECT rowid, * FROM %s WHERE %s", CommonUtil.getClassName(clazz), - expression[0]); - String[] params = new String[expression.length - 1]; - System.arraycopy(expression, 1, params, 0, params.length); - - return exeNormalDataSql(db, clazz, sql, params); - } - - /** - * 获取分页数据 - */ - List findData(SQLiteDatabase db, Class clazz, int page, int num, - String... expression) { - if (page < 1 || num < 1) { - return null; - } - db = checkDb(db); - CheckUtil.checkSqlExpression(expression); - String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s", - CommonUtil.getClassName(clazz), - expression[0], (page - 1) * num, num); - - String[] params = new String[expression.length - 1]; - System.arraycopy(expression, 1, params, 0, params.length); - - return exeNormalDataSql(db, clazz, sql, params); - } - - /** - * 模糊查寻数据 - */ - List findDataByFuzzy(SQLiteDatabase db, Class clazz, - String conditions) { - db = checkDb(db); - if (TextUtils.isEmpty(conditions)) { - throw new IllegalArgumentException("sql语句表达式不能为null或\"\""); - } - if (!conditions.toUpperCase().contains("LIKE")) { - throw new IllegalArgumentException("sql语句表达式未包含LIEK"); - } - String sql = String.format("SELECT rowid, * FROM %s, WHERE %s", CommonUtil.getClassName(clazz), - conditions); - return exeNormalDataSql(db, clazz, sql, null); - } - - /** - * 分页、模糊搜索数据 - */ - List findDataByFuzzy(SQLiteDatabase db, Class clazz, - int page, int num, String conditions) { - if (page < 1 || num < 1) { - return null; - } - db = checkDb(db); - if (TextUtils.isEmpty(conditions)) { - throw new IllegalArgumentException("sql语句表达式不能为null或\"\""); - } - if (!conditions.toUpperCase().contains("LIKE")) { - throw new IllegalArgumentException("sql语句表达式未包含LIEK"); - } - String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s", - CommonUtil.getClassName(clazz), conditions, (page - 1) * num, num); - return exeNormalDataSql(db, clazz, sql, null); - } - - /** - * 查找表的所有数据 - */ - List findAllData(SQLiteDatabase db, Class clazz) { - db = checkDb(db); - String sql = String.format("SELECT rowid, * FROM %s", CommonUtil.getClassName(clazz)); - return exeNormalDataSql(db, clazz, sql, null); - } - - /** - * 执行查询普通数据的sql语句,并创建对象 - * - * @param sql sql 查询语句 - * @param selectionArgs 查询参数,如何sql语句中查询条件含有'?'则该参数不能为空 - */ - private List exeNormalDataSql(SQLiteDatabase db, Class clazz, - String sql, String[] selectionArgs) { - print(FIND_DATA, sql); - Cursor cursor = db.rawQuery(sql, selectionArgs); - List data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; - closeCursor(cursor); - close(db); - return data; - } - - /** - * 根据数据游标创建一个具体的对象 - */ - private synchronized List newInstanceEntity(Class clazz, - Cursor cursor) { - List fields = CommonUtil.getAllFields(clazz); - List entitys = new ArrayList<>(); - if (fields != null && fields.size() > 0) { - try { - while (cursor.moveToNext()) { - T entity = clazz.newInstance(); - String primaryName = ""; - for (Field field : fields) { - field.setAccessible(true); - if (SqlUtil.isIgnore(field)) { - continue; - } - - Class type = field.getType(); - if (SqlUtil.isPrimary(field) && (type == int.class || type == Integer.class)) { - primaryName = field.getName(); - } - - int column = cursor.getColumnIndex(field.getName()); - if (column == -1) continue; - setFieldValue(type, field, column, cursor, entity); - } - //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 - entity.rowID = cursor.getInt( - cursor.getColumnIndex(TextUtils.isEmpty(primaryName) ? "rowid" : primaryName)); - //mDataCache.put(getCacheKey(entity), entity); - entitys.add(entity); - } - closeCursor(cursor); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - return entitys; - } - - /** - * 设置字段的值 - * - * @throws IllegalAccessException - */ - private void setFieldValue(Class type, Field field, int column, Cursor cursor, Object entity) - throws IllegalAccessException { - if (cursor == null || cursor.isClosed()) { - ALog.e(TAG, "cursor没有初始化"); - return; - } - if (type == String.class) { - String temp = cursor.getString(column); - if (!TextUtils.isEmpty(temp)) { - field.set(entity, URLDecoder.decode(temp)); - } - } else if (type == int.class || type == Integer.class) { - field.setInt(entity, cursor.getInt(column)); - } else if (type == float.class || type == Float.class) { - field.setFloat(entity, cursor.getFloat(column)); - } else if (type == double.class || type == Double.class) { - field.setDouble(entity, cursor.getDouble(column)); - } else if (type == long.class || type == Long.class) { - field.setLong(entity, cursor.getLong(column)); - } else if (type == boolean.class || type == Boolean.class) { - String temp = cursor.getString(column); - if (TextUtils.isEmpty(temp)) { - field.setBoolean(entity, false); - } else { - field.setBoolean(entity, !temp.equalsIgnoreCase("false")); - } - } else if (type == java.util.Date.class || type == java.sql.Date.class) { - field.set(entity, new Date(URLDecoder.decode(cursor.getString(column)))); - } else if (type == byte[].class) { - field.set(entity, cursor.getBlob(column)); - } else if (type == Map.class) { - String temp = cursor.getString(column); - if (!TextUtils.isEmpty(temp)) { - field.set(entity, SqlUtil.str2Map(URLDecoder.decode(temp))); - } - } else if (type == List.class) { - String value = cursor.getString(column); - if (!TextUtils.isEmpty(value)) { - field.set(entity, SqlUtil.str2List(URLDecoder.decode(value), field)); - } - } - } - - /** - * 获取所在行Id - */ - int[] getRowId(SQLiteDatabase db, Class clazz) { - db = checkDb(db); - Cursor cursor = db.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null); - int[] ids = new int[cursor.getCount()]; - int i = 0; - while (cursor.moveToNext()) { - ids[i] = cursor.getInt(cursor.getColumnIndex("rowid")); - i++; - } - cursor.close(); - close(db); - return ids; - } - - /** - * 获取行Id - */ - int getRowId(SQLiteDatabase db, Class clazz, Object[] wheres, Object[] values) { - db = checkDb(db); - if (wheres.length <= 0 || values.length <= 0) { - ALog.e(TAG, "请输入删除条件"); - return -1; - } else if (wheres.length != values.length) { - ALog.e(TAG, "groupHash 和 vaule 长度不相等"); - return -1; - } - StringBuilder sb = new StringBuilder(); - sb.append("SELECT rowid FROM ").append(CommonUtil.getClassName(clazz)).append(" WHERE "); - int i = 0; - for (Object where : wheres) { - sb.append(where).append("=").append("'").append(values[i]).append("'"); - sb.append(i >= wheres.length - 1 ? "" : ","); - i++; - } - print(ROW_ID, sb.toString()); - Cursor c = db.rawQuery(sb.toString(), null); - int id = c.getColumnIndex("rowid"); - c.close(); - close(db); - return id; - } - - /** - * 通过rowId判断数据是否存在 - */ - boolean itemExist(SQLiteDatabase db, Class clazz, long rowId) { - return itemExist(db, CommonUtil.getClassName(clazz), rowId); - } - - /** - * 通过rowId判断数据是否存在 - */ - boolean itemExist(SQLiteDatabase db, String tableName, long rowId) { - db = checkDb(db); - String sql = "SELECT rowid FROM " + tableName + " WHERE rowid=" + rowId; - print(ROW_ID, sql); - Cursor cursor = db.rawQuery(sql, null); - boolean isExist = cursor.getCount() > 0; - cursor.close(); - return isExist; - } -} +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.orm; + +import android.annotation.TargetApi; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.os.Build; +import android.text.TextUtils; +import com.arialyy.aria.orm.annotation.Many; +import com.arialyy.aria.orm.annotation.One; +import com.arialyy.aria.orm.annotation.Wrapper; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.CommonUtil; +import java.lang.reflect.Field; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by laoyuyu on 2018/3/22. + * 查询数据 + */ +class DelegateFind extends AbsDelegate { + private final String PARENT_COLUMN_ALIAS = "p"; + private final String CHILD_COLUMN_ALIAS = "c"; + + private DelegateFind() { + } + + /** + * 获取{@link One}和{@link Many}注解的字段 + * + * @return 返回[OneField, ManyField] ,如果注解依赖错误返回null + */ + private Field[] getOneAndManyField(Class clazz) { + Field[] om = new Field[2]; + Field[] fields = clazz.getDeclaredFields(); + Field one = null, many = null; + boolean hasOne = false, hasMany = false; + for (Field field : fields) { + if (SqlUtil.isOne(field)) { + if (hasOne) { + ALog.w(TAG, "查询数据失败,实体中有多个@One 注解"); + return null; + } + hasOne = true; + one = field; + } + if (SqlUtil.isMany(field)) { + if (hasMany) { + ALog.w(TAG, "查询数据失败,实体中有多个@Many 注解"); + return null; + } + if (!field.getType().isAssignableFrom(List.class)) { + ALog.w(TAG, "查询数据失败,@Many 注解的类型不是List"); + return null; + } + hasMany = true; + many = field; + } + } + + if (one == null || many == null) { + ALog.w(TAG, "查询数据失败,实体中没有@One或@Many注解"); + return null; + } + + if (many.getType() != List.class) { + ALog.w(TAG, "查询数据失败,@Many注解的字段必须是List"); + return null; + } + om[0] = one; + om[1] = many; + return om; + } + + /** + * 查找一对多的关联数据 + * 如果查找不到数据或实体没有被{@link Wrapper}注解,将返回null + * 如果实体中没有{@link One}或{@link Many}注解,将返回null + * 如果实体中有多个{@link One}或{@link Many}注解,将返回nul + * {@link One} 的注解对象必须是{@link DbEntity},{@link Many}的注解对象必须是List,并且List中的类型必须是{@link DbEntity} + */ + List findRelationData(SQLiteDatabase db, Class clazz, + String... expression) { + return exeRelationSql(db, clazz, -1, -1, expression); + } + + /** + * 查找一对多的关联数据 + * 如果查找不到数据或实体没有被{@link Wrapper}注解,将返回null + * 如果实体中没有{@link One}或{@link Many}注解,将返回null + * 如果实体中有多个{@link One}或{@link Many}注解,将返回nul + * {@link One} 的注解对象必须是{@link DbEntity},{@link Many}的注解对象必须是List,并且List中的类型必须是{@link DbEntity} + */ + List findRelationData(SQLiteDatabase db, Class clazz, + int page, int num, String... expression) { + if (page < 1 || num < 1) { + return null; + } + return exeRelationSql(db, clazz, page, num, expression); + } + + /** + * 执行关联查询,如果不需要分页,page和num传-1 + * + * @param page 当前页 + * @param num 一页的数量 + */ + private List exeRelationSql(SQLiteDatabase db, Class clazz, + int page, int num, String... expression) { + db = checkDb(db); + if (SqlUtil.isWrapper(clazz)) { + Field[] om = getOneAndManyField(clazz); + if (om == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + Field one = om[0], many = om[1]; + try { + Many m = many.getAnnotation(Many.class); + Class parentClazz = Class.forName(one.getType().getName()); + Class childClazz = Class.forName(CommonUtil.getListParamType(many).getName()); + final String pTableName = parentClazz.getSimpleName(); + final String cTableName = childClazz.getSimpleName(); + List pColumn = SqlUtil.getAllNotIgnoreField(parentClazz); + List cColumn = SqlUtil.getAllNotIgnoreField(childClazz); + List pColumnAlias = new ArrayList<>(); + List cColumnAlias = new ArrayList<>(); + StringBuilder pSb = new StringBuilder(); + StringBuilder cSb = new StringBuilder(); + + if (pColumn != null) { + pSb.append(pTableName.concat(".rowid AS ").concat(PARENT_COLUMN_ALIAS).concat("rowid,")); + for (Field f : pColumn) { + String temp = PARENT_COLUMN_ALIAS.concat(f.getName()); + pColumnAlias.add(temp); + pSb.append(pTableName.concat(".").concat(f.getName())) + .append(" AS ") + .append(temp) + .append(","); + } + } + + if (cColumn != null) { + pSb.append(cTableName.concat(".rowid AS ").concat(CHILD_COLUMN_ALIAS).concat("rowid,")); + for (Field f : cColumn) { + String temp = CHILD_COLUMN_ALIAS.concat(f.getName()); + cColumnAlias.add(temp); + cSb.append(cTableName.concat(".").concat(f.getName())) + .append(" AS ") + .append(temp) + .append(","); + } + } + + String pColumnAlia = pSb.toString(); + String cColumnAlia = cSb.toString(); + if (!TextUtils.isEmpty(pColumnAlia)) { + pColumnAlia = pColumnAlia.substring(0, pColumnAlia.length() - 1); + } + + if (!TextUtils.isEmpty(cColumnAlia)) { + cColumnAlia = cColumnAlia.substring(0, cColumnAlia.length() - 1); + } + + sb.append("SELECT "); + + if (!TextUtils.isEmpty(pColumnAlia)) { + sb.append(pColumnAlia).append(","); + } + if (!TextUtils.isEmpty(cColumnAlia)) { + sb.append(cColumnAlia); + } + if (TextUtils.isEmpty(pColumnAlia) && TextUtils.isEmpty(cColumnAlia)) { + sb.append(" * "); + } + + sb.append(" FROM ") + .append(pTableName) + .append(" INNER JOIN ") + .append(cTableName) + .append(" ON ") + .append(pTableName.concat(".").concat(m.parentColumn())) + .append(" = ") + .append(cTableName.concat(".").concat(m.entityColumn())); + String sql; + if (expression != null && expression.length > 0) { + CheckUtil.checkSqlExpression(expression); + sb.append(" WHERE ").append(expression[0]).append(" "); + sql = sb.toString(); + sql = sql.replace("?", "%s"); + Object[] params = new String[expression.length - 1]; + for (int i = 0, len = params.length; i < len; i++) { + params[i] = String.format("'%s'", encodeStr(expression[i + 1])); + } + sql = String.format(sql, params); + } else { + sql = sb.toString(); + } + if (page != -1 && num != -1) { + sql = sql.concat(String.format(" LIMIT %s,%s", (page - 1) * num, num)); + } + + print(RELATION, sql); + Cursor cursor = db.rawQuery(sql, null); + List data = + (List) newInstanceEntity(clazz, parentClazz, childClazz, cursor, pColumn, cColumn, + pColumnAlias, cColumnAlias); + closeCursor(cursor); + close(db); + return data; + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } else { + ALog.e(TAG, "查询数据失败,实体类没有使用@Wrapper 注解"); + return null; + } + return null; + } + + /** + * 创建关联查询的数据 + * + * @param pColumn 父表的所有字段 + * @param cColumn 字表的所有字段 + * @param pColumnAlias 关联查询父表别名 + * @param cColumnAlias 关联查询子表别名 + */ + private synchronized List newInstanceEntity( + Class clazz, Class

parent, + Class child, + Cursor cursor, + List pColumn, List cColumn, + List pColumnAlias, List cColumnAlias) { + try { + String parentPrimary = ""; //父表主键别名 + for (Field f : pColumn) { + if (SqlUtil.isPrimary(f)) { + parentPrimary = PARENT_COLUMN_ALIAS.concat(f.getName()); + break; + } + } + + List wrappers = new ArrayList<>(); + Map tempParent = new LinkedHashMap<>(); // 所有父表元素,key为父表主键的值 + Map> tempChild = new LinkedHashMap<>(); // 所有的字表元素,key为父表主键的值 + + Object old = null; + while (cursor.moveToNext()) { + //创建父实体 + Object ppValue = setPPValue(parentPrimary, cursor); + if (old == null || ppValue != old) { //当主键不同时,表示是不同的父表数据 + old = ppValue; + if (tempParent.get(old) == null) { + P pEntity = parent.newInstance(); + String pPrimaryName = ""; + for (int i = 0, len = pColumnAlias.size(); i < len; i++) { + Field pField = pColumn.get(i); + pField.setAccessible(true); + Class type = pField.getType(); + int column = cursor.getColumnIndex(pColumnAlias.get(i)); + if (column == -1) continue; + setFieldValue(type, pField, column, cursor, pEntity); + + if (SqlUtil.isPrimary(pField) && (type == int.class || type == Integer.class)) { + pPrimaryName = pField.getName(); + } + } + + //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 + pEntity.rowID = cursor.getInt( + cursor.getColumnIndex( + TextUtils.isEmpty(pPrimaryName) ? PARENT_COLUMN_ALIAS.concat("rowid") + : pPrimaryName)); + + tempParent.put(ppValue, pEntity); + } + } + + // 创建子实体 + C cEntity = child.newInstance(); + String cPrimaryName = ""; + for (int i = 0, len = cColumnAlias.size(); i < len; i++) { + Field cField = cColumn.get(i); + cField.setAccessible(true); + Class type = cField.getType(); + + int column = cursor.getColumnIndex(cColumnAlias.get(i)); + if (column == -1) continue; + setFieldValue(type, cField, column, cursor, cEntity); + + if (SqlUtil.isPrimary(cField) && (type == int.class || type == Integer.class)) { + cPrimaryName = cField.getName(); + } + } + //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 + cEntity.rowID = cursor.getInt( + cursor.getColumnIndex( + TextUtils.isEmpty(cPrimaryName) ? CHILD_COLUMN_ALIAS.concat("rowid") + : cPrimaryName)); + if (tempChild.get(old) == null) { + tempChild.put(old, new ArrayList()); + } + tempChild.get(old).add(cEntity); + } + + List wFields = SqlUtil.getAllNotIgnoreField(clazz); + if (wFields != null && !wFields.isEmpty()) { + Set pKeys = tempParent.keySet(); + for (Object pk : pKeys) { + T wrapper = clazz.newInstance(); + P p = tempParent.get(pk); + boolean isPSet = false, isCSet = false; + for (Field f : wFields) { + if (!isPSet && f.getAnnotation(One.class) != null) { + f.set(wrapper, p); + isPSet = true; + } + if (!isCSet && f.getAnnotation(Many.class) != null) { + f.set(wrapper, tempChild.get(pk)); + isCSet = true; + } + } + wrapper.handleConvert(); //处理下转换 + wrappers.add(wrapper); + } + } + return wrappers; + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取父表主键数据 + * + * @param parentPrimary 父表主键别名 + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) private Object setPPValue(String parentPrimary, + Cursor cursor) { + Object ppValue = null; + int ppColumn = cursor.getColumnIndex(parentPrimary); //父表主键所在的列 + int type = cursor.getType(ppColumn); + switch (type) { + case Cursor.FIELD_TYPE_INTEGER: + ppValue = cursor.getLong(ppColumn); + break; + case Cursor.FIELD_TYPE_FLOAT: + ppValue = cursor.getFloat(ppColumn); + break; + case Cursor.FIELD_TYPE_STRING: + ppValue = cursor.getString(ppColumn); + break; + } + return ppValue; + } + + /** + * 条件查寻数据 + */ + List findData(SQLiteDatabase db, Class clazz, String... expression) { + db = checkDb(db); + CheckUtil.checkSqlExpression(expression); + String sql = String.format("SELECT rowid, * FROM %s WHERE %s", CommonUtil.getClassName(clazz), + expression[0]); + String[] params = new String[expression.length - 1]; + System.arraycopy(expression, 1, params, 0, params.length); + + return exeNormalDataSql(db, clazz, sql, params); + } + + /** + * 获取分页数据 + */ + List findData(SQLiteDatabase db, Class clazz, int page, int num, + String... expression) { + if (page < 1 || num < 1) { + return null; + } + db = checkDb(db); + CheckUtil.checkSqlExpression(expression); + String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s", + CommonUtil.getClassName(clazz), + expression[0], (page - 1) * num, num); + + String[] params = new String[expression.length - 1]; + System.arraycopy(expression, 1, params, 0, params.length); + + return exeNormalDataSql(db, clazz, sql, params); + } + + /** + * 模糊查寻数据 + */ + List findDataByFuzzy(SQLiteDatabase db, Class clazz, + String conditions) { + db = checkDb(db); + if (TextUtils.isEmpty(conditions)) { + throw new IllegalArgumentException("sql语句表达式不能为null或\"\""); + } + if (!conditions.toUpperCase().contains("LIKE")) { + throw new IllegalArgumentException("sql语句表达式未包含LIEK"); + } + String sql = String.format("SELECT rowid, * FROM %s, WHERE %s", CommonUtil.getClassName(clazz), + conditions); + return exeNormalDataSql(db, clazz, sql, null); + } + + /** + * 分页、模糊搜索数据 + */ + List findDataByFuzzy(SQLiteDatabase db, Class clazz, + int page, int num, String conditions) { + if (page < 1 || num < 1) { + return null; + } + db = checkDb(db); + if (TextUtils.isEmpty(conditions)) { + throw new IllegalArgumentException("sql语句表达式不能为null或\"\""); + } + if (!conditions.toUpperCase().contains("LIKE")) { + throw new IllegalArgumentException("sql语句表达式未包含LIEK"); + } + String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s", + CommonUtil.getClassName(clazz), conditions, (page - 1) * num, num); + return exeNormalDataSql(db, clazz, sql, null); + } + + /** + * 查找表的所有数据 + */ + List findAllData(SQLiteDatabase db, Class clazz) { + db = checkDb(db); + String sql = String.format("SELECT rowid, * FROM %s", CommonUtil.getClassName(clazz)); + return exeNormalDataSql(db, clazz, sql, null); + } + + /** + * 执行查询普通数据的sql语句,并创建对象 + * + * @param sql sql 查询语句 + * @param selectionArgs 查询参数,如何sql语句中查询条件含有'?'则该参数不能为空 + */ + private List exeNormalDataSql(SQLiteDatabase db, Class clazz, + String sql, String[] selectionArgs) { + print(FIND_DATA, sql); + String[] temp = new String[selectionArgs.length]; + int i = 0; + for (String arg : selectionArgs){ + temp[i] = encodeStr(arg); + i ++; + } + Cursor cursor = db.rawQuery(sql, temp); + List data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; + closeCursor(cursor); + close(db); + return data; + } + + /** + * 根据数据游标创建一个具体的对象 + */ + private synchronized List newInstanceEntity(Class clazz, + Cursor cursor) { + List fields = CommonUtil.getAllFields(clazz); + List entitys = new ArrayList<>(); + if (fields != null && fields.size() > 0) { + try { + while (cursor.moveToNext()) { + T entity = clazz.newInstance(); + String primaryName = ""; + for (Field field : fields) { + field.setAccessible(true); + if (SqlUtil.isIgnore(field)) { + continue; + } + + Class type = field.getType(); + if (SqlUtil.isPrimary(field) && (type == int.class || type == Integer.class)) { + primaryName = field.getName(); + } + + int column = cursor.getColumnIndex(field.getName()); + if (column == -1) continue; + setFieldValue(type, field, column, cursor, entity); + } + //当设置了主键,而且主键的类型为integer时,查询RowID等于主键 + entity.rowID = cursor.getInt( + cursor.getColumnIndex(TextUtils.isEmpty(primaryName) ? "rowid" : primaryName)); + //mDataCache.put(getCacheKey(entity), entity); + entitys.add(entity); + } + closeCursor(cursor); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return entitys; + } + + /** + * 设置字段的值 + * + * @throws IllegalAccessException + */ + private void setFieldValue(Class type, Field field, int column, Cursor cursor, Object entity) + throws IllegalAccessException { + if (cursor == null || cursor.isClosed()) { + ALog.e(TAG, "cursor没有初始化"); + return; + } + if (type == String.class) { + String temp = cursor.getString(column); + if (!TextUtils.isEmpty(temp)) { + field.set(entity, URLDecoder.decode(temp)); + } + } else if (type == int.class || type == Integer.class) { + field.setInt(entity, cursor.getInt(column)); + } else if (type == float.class || type == Float.class) { + field.setFloat(entity, cursor.getFloat(column)); + } else if (type == double.class || type == Double.class) { + field.setDouble(entity, cursor.getDouble(column)); + } else if (type == long.class || type == Long.class) { + field.setLong(entity, cursor.getLong(column)); + } else if (type == boolean.class || type == Boolean.class) { + String temp = cursor.getString(column); + if (TextUtils.isEmpty(temp)) { + field.setBoolean(entity, false); + } else { + field.setBoolean(entity, !temp.equalsIgnoreCase("false")); + } + } else if (type == java.util.Date.class || type == java.sql.Date.class) { + field.set(entity, new Date(URLDecoder.decode(cursor.getString(column)))); + } else if (type == byte[].class) { + field.set(entity, cursor.getBlob(column)); + } else if (type == Map.class) { + String temp = cursor.getString(column); + if (!TextUtils.isEmpty(temp)) { + field.set(entity, SqlUtil.str2Map(URLDecoder.decode(temp))); + } + } else if (type == List.class) { + String value = cursor.getString(column); + if (!TextUtils.isEmpty(value)) { + field.set(entity, SqlUtil.str2List(URLDecoder.decode(value), field)); + } + } + } + + /** + * 获取所在行Id + */ + int[] getRowId(SQLiteDatabase db, Class clazz) { + db = checkDb(db); + Cursor cursor = db.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null); + int[] ids = new int[cursor.getCount()]; + int i = 0; + while (cursor.moveToNext()) { + ids[i] = cursor.getInt(cursor.getColumnIndex("rowid")); + i++; + } + cursor.close(); + close(db); + return ids; + } + + /** + * 获取行Id + */ + int getRowId(SQLiteDatabase db, Class clazz, Object[] wheres, Object[] values) { + db = checkDb(db); + if (wheres.length <= 0 || values.length <= 0) { + ALog.e(TAG, "请输入删除条件"); + return -1; + } else if (wheres.length != values.length) { + ALog.e(TAG, "groupHash 和 vaule 长度不相等"); + return -1; + } + StringBuilder sb = new StringBuilder(); + sb.append("SELECT rowid FROM ").append(CommonUtil.getClassName(clazz)).append(" WHERE "); + int i = 0; + for (Object where : wheres) { + sb.append(where).append("=").append("'").append(values[i]).append("'"); + sb.append(i >= wheres.length - 1 ? "" : ","); + i++; + } + print(ROW_ID, sb.toString()); + Cursor c = db.rawQuery(sb.toString(), null); + int id = c.getColumnIndex("rowid"); + c.close(); + close(db); + return id; + } + + /** + * 通过rowId判断数据是否存在 + */ + boolean itemExist(SQLiteDatabase db, Class clazz, long rowId) { + return itemExist(db, CommonUtil.getClassName(clazz), rowId); + } + + /** + * 通过rowId判断数据是否存在 + */ + boolean itemExist(SQLiteDatabase db, String tableName, long rowId) { + db = checkDb(db); + String sql = "SELECT rowid FROM " + tableName + " WHERE rowid=" + rowId; + print(ROW_ID, sql); + Cursor cursor = db.rawQuery(sql, null); + boolean isExist = cursor.getCount() > 0; + cursor.close(); + return isExist; + } +} diff --git a/DEV_LOG.md b/DEV_LOG.md index 53178e29..897e344c 100644 --- a/DEV_LOG.md +++ b/DEV_LOG.md @@ -1,8 +1,11 @@ ## 开发日志 + + v_3.6.3 (2019/4/2) + - fix bug https://github.com/AriaLyy/Aria/issues/377 + v_3.6.2 (2019/4/1) - fix bug https://github.com/AriaLyy/Aria/issues/368 - 增加gradle 5.0支持 - fix bug https://github.com/AriaLyy/Aria/issues/374 + - 增加分页功能,详情见:https://aria.laoyuyu.me/aria_doc/api/task_list.html#%E4%BB%BB%E5%8A%A1%E5%88%97%E8%A1%A8%E5%88%86%E9%A1%B5%EF%BC%88362%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81%EF%BC%89 + v_3.6.1 (2019/3/5) - fix bug https://github.com/AriaLyy/Aria/issues/367 + v_3.6 (2019/2/27) diff --git a/README.md b/README.md index d9c7a5fd..249a8790 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ Aria有以下特点: [![Compiler](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion) ```java -compile 'com.arialyy.aria:aria-core:3.6.2' -annotationProcessor 'com.arialyy.aria:aria-compiler:3.6.2' +compile 'com.arialyy.aria:aria-core:3.6.3' +annotationProcessor 'com.arialyy.aria:aria-compiler:3.6.3' ``` 如果出现android support依赖错误,请将 `compile 'com.arialyy.aria:aria-core:'`替换为 ``` @@ -104,10 +104,12 @@ protected void onCreate(Bundle savedInstanceState) { ### 版本日志 - + v_3.6.2 (2019/4/1) - - fix bug https://github.com/AriaLyy/Aria/issues/368 - - 增加gradle 5.0支持 - - fix bug https://github.com/AriaLyy/Aria/issues/374 +* v3.6.3 (2019/4/2) + - fix bug https://github.com/AriaLyy/Aria/issues/368 + - 增加gradle 5.0支持 + - fix bug https://github.com/AriaLyy/Aria/issues/374 + - fix bug https://github.com/AriaLyy/Aria/issues/377 + - 增加分页获取任务列表api, 详情见:https://aria.laoyuyu.me/aria_doc/api/task_list.html#%E4%BB%BB%E5%8A%A1%E5%88%97%E8%A1%A8%E5%88%86%E9%A1%B5%EF%BC%88362%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81%EF%BC%89 [更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md) diff --git a/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java index 412d4f0c..8e3fc570 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.Environment; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -290,9 +291,9 @@ public class SingleTaskActivity extends BaseActivity { public void onClick(View view) { switch (view.getId()) { case R.id.start: - //startD(); - List list = Aria.download(this).getAllNotCompleteTask(5, 2); - ALog.d("Tag", list.size() + ""); + startD(); + //List list = Aria.download(this).getAllNotCompleteTask(5, 2); + //ALog.d("Tag", list.size() + ""); break; case R.id.stop: Aria.download(this).load(DOWNLOAD_URL).stop(); @@ -313,8 +314,8 @@ public class SingleTaskActivity extends BaseActivity { private void startD() { //Aria.get(this).setLogLevel(ALog.LOG_CLOSE); //Aria.download(this).load("aaaa.apk"); - //String path = Environment.getExternalStorageDirectory().getPath() + "/ggsg11.ota"; - String path = String.format("/sdcard/ggsg11(%s).mp4", i); + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ggsg11.mp4"; + //String path = String.format("/sdcard/ggsg11(%s).mp4", i); //if (new File(path).exists()) { // // i++; @@ -343,7 +344,7 @@ public class SingleTaskActivity extends BaseActivity { // + "\"id\":\"你的样子\"\n< > " // + "}") //.resetState() - .save(); + .start(); //.add(); } diff --git a/build.gradle b/build.gradle index 3195ccff..1512fb90 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ task clean(type: Delete) { ext { userOrg = 'arialyy' groupId = 'com.arialyy.aria' - publishVersion = '3.6.2' + publishVersion = '3.6.3' // publishVersion = '1.0.4' //FTP插件 repoName='maven' desc = 'android 下载框架'