parent
4bd2ff7e18
commit
6aa63ff699
@ -0,0 +1,174 @@ |
|||||||
|
/* |
||||||
|
* 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.content.ContentProvider |
||||||
|
import android.content.ContentValues |
||||||
|
import android.content.Context |
||||||
|
import android.database.Cursor |
||||||
|
import android.net.Uri |
||||||
|
import com.arialyy.aria.util.ALog |
||||||
|
import com.arialyy.aria.util.CommonUtil |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 2:25 下午 2022/4/25 |
||||||
|
**/ |
||||||
|
class DbContentProvider : ContentProvider() { |
||||||
|
val TAG = "DbContentProvider" |
||||||
|
|
||||||
|
companion object { |
||||||
|
// const val KEY_TABLE_NAME = "tableName" |
||||||
|
const val KEY_ROW_ID = "rowId" |
||||||
|
const val KEY_TABLE_CLAZZ = "tableClazz" |
||||||
|
const val KEY_LIMIT = "limit" |
||||||
|
|
||||||
|
fun createRequestUrl(context: Context, clazz: Class<*>): Uri { |
||||||
|
return Uri.parse("content://${context.packageName}.com.arialyy.aria.provide/request?${KEY_TABLE_CLAZZ}=${clazz.name}") |
||||||
|
} |
||||||
|
|
||||||
|
fun getRequestUrl(context: Context): String { |
||||||
|
return "content://${context.packageName}.com.arialyy.aria.provide/request" |
||||||
|
} |
||||||
|
|
||||||
|
fun getResponseUrl(context: Context): String { |
||||||
|
return "content://${context.packageName}.com.arialyy.aria.provide/response" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* key: clazzPath, value: tableName |
||||||
|
*/ |
||||||
|
private val tableExistMap = mutableMapOf<String, String>() |
||||||
|
|
||||||
|
private lateinit var helper: SqlHelper |
||||||
|
|
||||||
|
override fun onCreate(): Boolean { |
||||||
|
helper = SqlHelper.init(context) |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
private fun getTableName(uri: Uri): String? { |
||||||
|
val db = SqlUtil.checkDb(helper.db) |
||||||
|
val clazzName = uri.getQueryParameter(KEY_TABLE_CLAZZ) |
||||||
|
if (tableExistMap[clazzName!!] != null) { |
||||||
|
return tableExistMap[clazzName] |
||||||
|
} |
||||||
|
|
||||||
|
val clazz: Class<out DbEntity>? = |
||||||
|
javaClass.classLoader?.loadClass(clazzName) as Class<out DbEntity>? |
||||||
|
if (clazz == null) { |
||||||
|
ALog.e(TAG, "【$clazz】为空") |
||||||
|
return null |
||||||
|
} |
||||||
|
SqlUtil.checkOrCreateTable(db, clazz) |
||||||
|
val tableName = CommonUtil.getClassName(clazz) |
||||||
|
tableExistMap[clazzName] = tableName |
||||||
|
return tableName |
||||||
|
} |
||||||
|
|
||||||
|
override fun query( |
||||||
|
uri: Uri, |
||||||
|
projection: Array<out String>?, |
||||||
|
selection: String?, |
||||||
|
selectionArgs: Array<out String>?, |
||||||
|
sortOrder: String? |
||||||
|
): Cursor? { |
||||||
|
val db = SqlUtil.checkDb(helper.db) |
||||||
|
val tableName = getTableName(uri) |
||||||
|
if (tableName.isNullOrBlank()) { |
||||||
|
return null |
||||||
|
} |
||||||
|
val clazzName = uri.getQueryParameter(KEY_TABLE_CLAZZ) |
||||||
|
val clazz = javaClass.classLoader?.loadClass(clazzName) as Class<out DbEntity>? |
||||||
|
val columns = SqlUtil.getColumns(clazz) |
||||||
|
val limit = uri.getQueryParameter(KEY_LIMIT) |
||||||
|
return db.query( |
||||||
|
tableName, |
||||||
|
columns.toTypedArray(), |
||||||
|
selection, |
||||||
|
selectionArgs, |
||||||
|
null, |
||||||
|
null, |
||||||
|
null, |
||||||
|
limit |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
override fun getType(uri: Uri): String? { |
||||||
|
return null |
||||||
|
} |
||||||
|
|
||||||
|
override fun insert(uri: Uri, values: ContentValues?): Uri? { |
||||||
|
val db = SqlUtil.checkDb(helper.db) |
||||||
|
val tableName = getTableName(uri) |
||||||
|
if (tableName.isNullOrBlank()) { |
||||||
|
return null |
||||||
|
} |
||||||
|
db.beginTransaction() |
||||||
|
try { |
||||||
|
val rowId = db.insert(tableName, null, values) |
||||||
|
if (rowId == -1L) { |
||||||
|
return null |
||||||
|
} |
||||||
|
return Uri.parse("${getResponseUrl(context!!)}?${KEY_ROW_ID}=$rowId") |
||||||
|
} finally { |
||||||
|
db.endTransaction() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int { |
||||||
|
val db = SqlUtil.checkDb(helper.db) |
||||||
|
val tableName = getTableName(uri) |
||||||
|
if (tableName.isNullOrBlank()) { |
||||||
|
return -1 |
||||||
|
} |
||||||
|
db.beginTransaction() |
||||||
|
try { |
||||||
|
val rowId = db.delete(tableName, selection, selectionArgs) |
||||||
|
if (rowId == -1) { |
||||||
|
return -1 |
||||||
|
} |
||||||
|
return rowId |
||||||
|
} finally { |
||||||
|
db.endTransaction() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun update( |
||||||
|
uri: Uri, |
||||||
|
values: ContentValues?, |
||||||
|
selection: String?, |
||||||
|
selectionArgs: Array<out String>? |
||||||
|
): Int { |
||||||
|
val db = SqlUtil.checkDb(helper.db) |
||||||
|
val tableName = getTableName(uri) |
||||||
|
if (tableName.isNullOrBlank()) { |
||||||
|
return -1 |
||||||
|
} |
||||||
|
db.beginTransaction() |
||||||
|
try { |
||||||
|
val rowId = db.update(tableName, values, selection, selectionArgs) |
||||||
|
if (rowId == -1) { |
||||||
|
return -1 |
||||||
|
} |
||||||
|
return rowId |
||||||
|
} finally { |
||||||
|
db.endTransaction() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,83 @@ |
|||||||
|
package com.arialyy.aria.orm |
||||||
|
|
||||||
|
import android.content.ContentValues |
||||||
|
import android.text.TextUtils |
||||||
|
import com.arialyy.aria.orm.annotation.Primary |
||||||
|
import com.arialyy.aria.util.CommonUtil |
||||||
|
import java.lang.reflect.Field |
||||||
|
import java.lang.reflect.Type |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 2:58 下午 2022/4/25 |
||||||
|
**/ |
||||||
|
internal object DbUtil { |
||||||
|
/** |
||||||
|
* 创建存储数据\更新数据时使用的ContentValues |
||||||
|
* |
||||||
|
* @return 如果没有字段属性,返回null |
||||||
|
*/ |
||||||
|
fun createValues(dbEntity: DbEntity): ContentValues? { |
||||||
|
val fields = CommonUtil.getAllFields(dbEntity.javaClass) |
||||||
|
if (fields.size > 0) { |
||||||
|
val values = ContentValues() |
||||||
|
try { |
||||||
|
for (field in fields) { |
||||||
|
field.isAccessible = true |
||||||
|
if (isIgnore(dbEntity, field)) { |
||||||
|
continue |
||||||
|
} |
||||||
|
var value: String? = null |
||||||
|
val type: Type = field.type |
||||||
|
if (type === MutableMap::class.java && SqlUtil.checkMap(field)) { |
||||||
|
value = SqlUtil.map2Str(field[dbEntity] as Map<String?, String?>) |
||||||
|
} else if (type === MutableList::class.java && SqlUtil.checkList(field)) { |
||||||
|
value = SqlUtil.list2Str(dbEntity, field) |
||||||
|
} else { |
||||||
|
val obj = field[dbEntity] |
||||||
|
if (obj != null) { |
||||||
|
value = field[dbEntity].toString() |
||||||
|
} |
||||||
|
} |
||||||
|
values.put(field.name, SqlUtil.encodeStr(value)) |
||||||
|
} |
||||||
|
return values |
||||||
|
} catch (e: IllegalAccessException) { |
||||||
|
e.printStackTrace() |
||||||
|
} |
||||||
|
} |
||||||
|
return null |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* `true`自动增长的主键和需要忽略的字段 |
||||||
|
*/ |
||||||
|
@Throws(IllegalAccessException::class) private fun isIgnore(obj: Any, field: Field): Boolean { |
||||||
|
if (SqlUtil.isIgnore(field)) { |
||||||
|
return true |
||||||
|
} |
||||||
|
// 忽略为空的字段 |
||||||
|
val value = field[obj] ?: return true |
||||||
|
if (value is String) { |
||||||
|
if (TextUtils.isEmpty(value.toString())) { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
if (value is List<*>) { |
||||||
|
if (value.size == 0) { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
if (value is Map<*, *>) { |
||||||
|
if (value.size == 0) { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
if (SqlUtil.isPrimary(field)) { //忽略自动增长的主键 |
||||||
|
val p = field.getAnnotation(Primary::class.java) |
||||||
|
return p.autoincrement |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
/* |
||||||
|
* 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.content.Context |
||||||
|
import com.arialyy.aria.util.ALog |
||||||
|
import com.arialyy.aria.util.CommonUtil |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 3:55 下午 2022/4/25 |
||||||
|
**/ |
||||||
|
class DelegateDel : AbsDelegate() { |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除某条数据 |
||||||
|
*/ |
||||||
|
@Synchronized fun <T : DbEntity?> delData( |
||||||
|
context: Context, |
||||||
|
clazz: Class<T>, |
||||||
|
vararg expression: String |
||||||
|
) { |
||||||
|
if (!CommonUtil.checkSqlExpression(*expression)) { |
||||||
|
return |
||||||
|
} |
||||||
|
val selectionArgs = arrayOfNulls<String>(expression.size - 1) |
||||||
|
expression.forEachIndexed { index, s -> |
||||||
|
if (index == 0) { |
||||||
|
return@forEachIndexed |
||||||
|
} |
||||||
|
selectionArgs[index - 1] = s |
||||||
|
} |
||||||
|
|
||||||
|
val uri = DbContentProvider.createRequestUrl(context, clazz) |
||||||
|
val rowId = context.contentResolver.delete(uri, expression[0], selectionArgs) |
||||||
|
if (rowId != -1) { |
||||||
|
ALog.d(TAG, "删除成功,删除的rowId = $rowId") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,56 @@ |
|||||||
|
/* |
||||||
|
* 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.content.ContentValues |
||||||
|
import android.content.Context |
||||||
|
import com.arialyy.aria.util.ALog |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 2:50 下午 2022/4/25 |
||||||
|
**/ |
||||||
|
class DelegateInsert : AbsDelegate() { |
||||||
|
/** |
||||||
|
* 插入多条记录 |
||||||
|
*/ |
||||||
|
@Synchronized fun <T : DbEntity> insertManyData(context: Context, dbEntities: List<T>) { |
||||||
|
for (entity in dbEntities) { |
||||||
|
insertData(context, entity) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 插入数据 |
||||||
|
*/ |
||||||
|
@Synchronized fun insertData(context: Context, dbEntity: DbEntity) { |
||||||
|
val value: ContentValues? = DbUtil.createValues(dbEntity) |
||||||
|
if (value == null) { |
||||||
|
ALog.e(TAG, "保存记录失败,记录没有属性字段") |
||||||
|
} else { |
||||||
|
val uri = DbContentProvider.createRequestUrl(context, dbEntity.javaClass) |
||||||
|
val responseUri = context.contentResolver.insert(uri, value) |
||||||
|
val rowId = responseUri?.getQueryParameter(DbContentProvider.KEY_ROW_ID) |
||||||
|
if (rowId.isNullOrBlank()) { |
||||||
|
ALog.e(TAG, "插入失败,rowId为空") |
||||||
|
} else { |
||||||
|
dbEntity.rowID = rowId.toLong() |
||||||
|
ALog.d(TAG, "插入完成,responseUrl = $responseUri") |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue