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") |
||||
} |
||||
} |
||||
} |
@ -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