parent
2db3579f46
commit
2ef9550d86
@ -0,0 +1,44 @@ |
||||
/* |
||||
* 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.core.download; |
||||
|
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
*/ |
||||
@Wrapper |
||||
public class DownloadGroupTaskWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public DownloadGroupEntity entity; |
||||
|
||||
@Many(parentColumn = "key", entityColumn = "groupName") |
||||
private List<DownloadGroupTaskEntity> taskEntitys; |
||||
|
||||
public DownloadGroupTaskEntity taskEntity; |
||||
|
||||
@Override protected void handleConvert() { |
||||
taskEntity = (taskEntitys == null || taskEntitys.isEmpty()) ? null : taskEntitys.get(0); |
||||
if (taskEntity != null) { |
||||
taskEntity.setEntity(entity); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,41 @@ |
||||
/* |
||||
* 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.core.download; |
||||
|
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
*/ |
||||
@Wrapper |
||||
public class DownloadGroupWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public DownloadGroupEntity groupEntity; |
||||
|
||||
@Many(parentColumn = "groupName", entityColumn = "groupName") |
||||
public List<DownloadEntity> subEntity; |
||||
|
||||
@Override protected void handleConvert() { |
||||
if (subEntity != null && !subEntity.isEmpty()) { |
||||
groupEntity.setSubTasks(subEntity); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
/* |
||||
* 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.core.download; |
||||
|
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
*/ |
||||
@Wrapper |
||||
public class DownloadTaskWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public DownloadEntity entity; |
||||
|
||||
@Many(parentColumn = "downloadPath", entityColumn = "key") |
||||
private List<DownloadTaskEntity> taskEntitys = null; |
||||
|
||||
public DownloadTaskEntity taskEntity; |
||||
|
||||
@Override public void handleConvert() { |
||||
taskEntity = (taskEntitys == null || taskEntitys.isEmpty()) ? null : taskEntitys.get(0); |
||||
if (taskEntity != null) { |
||||
taskEntity.entity = entity; |
||||
} |
||||
} |
||||
} |
@ -1,86 +0,0 @@ |
||||
/* |
||||
* 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.core.manager; |
||||
|
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.core.inf.AbsTask; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.Iterator; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* Created by Aria.Lao on 2017/9/1. |
||||
* 任务管理器 |
||||
*/ |
||||
class TaskManager { |
||||
private static final String TAG = "TaskManager"; |
||||
private static volatile TaskManager INSTANCE = null; |
||||
private Map<String, AbsTask> map = new ConcurrentHashMap<>(); |
||||
|
||||
public static TaskManager getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (TaskManager.class) { |
||||
INSTANCE = new TaskManager(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
private TaskManager() { |
||||
|
||||
} |
||||
|
||||
/** |
||||
* 管理器添加任务 |
||||
* |
||||
* @param key 任务的key,下载为保存路径,任务组为任务组名,上传为文件上传路径 |
||||
* @param task 任务 |
||||
* @return {@code true}添加成功 |
||||
*/ |
||||
public <T extends AbsTask> boolean addTask(String key, Class<T> clazz, T task) { |
||||
String hash = CommonUtil.keyToHashKey(key); |
||||
if (map.keySet().contains(hash)) { |
||||
ALog.e(TAG, "任务【" + key + "】已存在"); |
||||
return false; |
||||
} |
||||
map.put(CommonUtil.keyToHashKey(key), task); |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 移除任务 |
||||
* |
||||
* @param key 任务的key,下载为保存路径,任务组为任务组名,上传为文件上传路径 |
||||
*/ |
||||
public void removeTask(String key) { |
||||
String hash = CommonUtil.keyToHashKey(key); |
||||
for (Iterator<Map.Entry<String, AbsTask>> iter = map.entrySet().iterator(); iter.hasNext(); ) { |
||||
Map.Entry<String, AbsTask> entry = iter.next(); |
||||
if (entry.getKey().equals(hash)) iter.remove(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 通过key获取任务 |
||||
* |
||||
* @return 如果找不到任务,返回null,否则返回key对应的任务 |
||||
*/ |
||||
public AbsTask getTask(String key) { |
||||
return map.get(CommonUtil.keyToHashKey(key)); |
||||
} |
||||
} |
@ -0,0 +1,45 @@ |
||||
/* |
||||
* 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.core.upload; |
||||
|
||||
import com.arialyy.aria.orm.AbsWrapper; |
||||
import com.arialyy.aria.orm.annotation.Many; |
||||
import com.arialyy.aria.orm.annotation.One; |
||||
import com.arialyy.aria.orm.annotation.Wrapper; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/30. |
||||
*/ |
||||
@Wrapper |
||||
public class UploadTaskWrapper extends AbsWrapper { |
||||
|
||||
@One |
||||
public UploadEntity entity; |
||||
|
||||
@Many(parentColumn = "filePath", entityColumn = "key") |
||||
private List<UploadTaskEntity> taskEntitys = null; |
||||
|
||||
public UploadTaskEntity taskEntity; |
||||
|
||||
@Override public void handleConvert() { |
||||
//taskEntity.entity = (tEntity == null || tEntity.isEmpty()) ? null : tEntity.get(0);
|
||||
taskEntity = (taskEntitys == null || taskEntitys.isEmpty()) ? null : taskEntitys.get(0); |
||||
if (taskEntity != null) { |
||||
taskEntity.entity = entity; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,162 @@ |
||||
/* |
||||
* 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.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.support.v4.util.LruCache; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.lang.reflect.Field; |
||||
import java.net.URLEncoder; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
*/ |
||||
abstract class AbsDelegate { |
||||
static final String TAG = "AbsDelegate"; |
||||
static final int CREATE_TABLE = 0; |
||||
static final int TABLE_EXISTS = 1; |
||||
static final int INSERT_DATA = 2; |
||||
static final int MODIFY_DATA = 3; |
||||
static final int FIND_DATA = 4; |
||||
static final int FIND_ALL_DATA = 5; |
||||
static final int DEL_DATA = 6; |
||||
static final int ROW_ID = 7; |
||||
static final int RELATION = 8; |
||||
static final int DROP_TABLE = 9; |
||||
|
||||
static LruCache<String, DbEntity> mDataCache = new LruCache<>(1024); |
||||
|
||||
/** |
||||
* 打印数据库日志 |
||||
* |
||||
* @param type {@link DelegateWrapper} |
||||
*/ |
||||
static void print(int type, String sql) { |
||||
if (!ALog.DEBUG) { |
||||
return; |
||||
} |
||||
String str = ""; |
||||
switch (type) { |
||||
case CREATE_TABLE: |
||||
str = "创建表 >>>> "; |
||||
break; |
||||
case TABLE_EXISTS: |
||||
str = "表是否存在 >>>> "; |
||||
break; |
||||
case INSERT_DATA: |
||||
str = "插入数据 >>>> "; |
||||
break; |
||||
case MODIFY_DATA: |
||||
str = "修改数据 >>>> "; |
||||
break; |
||||
case FIND_DATA: |
||||
str = "查询一行数据 >>>> "; |
||||
break; |
||||
case FIND_ALL_DATA: |
||||
str = "遍历整个数据库 >>>> "; |
||||
break; |
||||
case ROW_ID: |
||||
str = "查询RowId >>> "; |
||||
break; |
||||
case RELATION: |
||||
str = "查询关联表 >>> "; |
||||
break; |
||||
case DROP_TABLE: |
||||
str = "删除表 >>> "; |
||||
break; |
||||
} |
||||
ALog.d(TAG, str.concat(sql)); |
||||
} |
||||
|
||||
String getCacheKey(DbEntity dbEntity) { |
||||
return dbEntity.getClass().getName() + "_" + dbEntity.rowID; |
||||
} |
||||
|
||||
/** |
||||
* 检查list参数是否合法,list只能是{@code List<String>} |
||||
* |
||||
* @return {@code true} 合法 |
||||
*/ |
||||
boolean checkList(Field list) { |
||||
Class t = CommonUtil.getListParamType(list); |
||||
if (t != null && t == String.class) { |
||||
return true; |
||||
} else { |
||||
ALog.d(TAG, "map参数错误,支持List<String>的参数字段"); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 检查map参数是否合法,map只能是{@code Map<String, String>} |
||||
* |
||||
* @return {@code true} 合法 |
||||
*/ |
||||
boolean checkMap(Field map) { |
||||
Class[] ts = CommonUtil.getMapParamType(map); |
||||
if (ts != null |
||||
&& ts[0] != null |
||||
&& ts[1] != null |
||||
&& ts[0] == String.class |
||||
&& ts[1] == String.class) { |
||||
return true; |
||||
} else { |
||||
ALog.d(TAG, "map参数错误,支持Map<String,String>的参数字段"); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 为了防止特殊字符串导致存储失败,需要使用URL编码保存的字符串 |
||||
* |
||||
* @param value 需要保存的内容 |
||||
* @return 转换后的内容 |
||||
*/ |
||||
String convertValue(String value) { |
||||
if (value.contains("'")) { |
||||
return URLEncoder.encode(value); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
void closeCursor(Cursor cursor) { |
||||
if (cursor != null && !cursor.isClosed()) { |
||||
try { |
||||
cursor.close(); |
||||
} catch (android.database.SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void close(SQLiteDatabase db) { |
||||
//if (db != null && db.isOpen()) db.close();
|
||||
} |
||||
|
||||
/** |
||||
* 检查数据库是否关闭,已经关闭的话,打开数据库 |
||||
* |
||||
* @return 返回数据库 |
||||
*/ |
||||
SQLiteDatabase checkDb(SQLiteDatabase db) { |
||||
if (db == null || !db.isOpen()) { |
||||
db = SqlHelper.INSTANCE.getWritableDatabase(); |
||||
} |
||||
return db; |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
/* |
||||
* 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 com.arialyy.aria.orm.annotation.Foreign; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* on update 或 on delete 都可跟不同action功能 |
||||
* |
||||
* @see <a href="https://sqlite.org/foreignkeys.html"></a> |
||||
* {@link Foreign#onDelete()}、{@link Foreign#onUpdate()} |
||||
*/ |
||||
public enum ActionPolicy { |
||||
|
||||
/** |
||||
* 如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作 |
||||
*/ |
||||
NO_ACTION("NO ACTION"), |
||||
|
||||
/** |
||||
* 和NO ACTION 作用一致,和NO ACTION的区别是: |
||||
* 主表update/delete执行时,马上就触发约束; |
||||
* 而NO ACTION 是执行完成语句后才触发约束, |
||||
*/ |
||||
RESTRICT("RESTRICT"), |
||||
|
||||
/** |
||||
* 在父表上update/delete记录时,将子表上匹配记录的列设为null (要注意子表的外键列不能为not null) |
||||
*/ |
||||
SET_NULL("SET NULL"), |
||||
|
||||
/** |
||||
* 父表有变更时,子表将外键列设置成一个默认的值,default配置的值 |
||||
*/ |
||||
SET_DEFAULT("SET DEFAULT"), |
||||
|
||||
/** |
||||
* 在父表上update/delete记录时,同步update/delete掉子表的匹配记录 |
||||
*/ |
||||
CASCADE("CASCADE"); |
||||
|
||||
String function; |
||||
|
||||
ActionPolicy(String function) { |
||||
this.function = function; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,110 @@ |
||||
/* |
||||
* 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 android.content.ContextWrapper; |
||||
import android.database.DatabaseErrorHandler; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.os.Environment; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* 保存在sd卡的数据库使用的Context |
||||
*/ |
||||
class DatabaseContext extends ContextWrapper { |
||||
public DatabaseContext(Context context) { |
||||
super(context); |
||||
} |
||||
|
||||
/** |
||||
* 获得数据库路径,如果不存在,则创建对象对象 |
||||
*/ |
||||
@Override |
||||
public File getDatabasePath(String name) { |
||||
//判断是否存在sd卡
|
||||
boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals( |
||||
android.os.Environment.getExternalStorageState()); |
||||
if (!sdExist) { |
||||
return null; |
||||
} else { |
||||
//获取sd卡路径
|
||||
File file = getBaseContext().getExternalFilesDir(null); |
||||
String dbDir; |
||||
if (file != null) { |
||||
dbDir = file.getPath() + "/"; |
||||
} else { |
||||
dbDir = Environment.getExternalStorageDirectory().getPath() |
||||
+ "/Android/data/" |
||||
+ getBaseContext().getPackageName() |
||||
+ "/files/"; |
||||
} |
||||
|
||||
dbDir += "DB";//数据库所在目录
|
||||
String dbPath = dbDir + "/" + name;//数据库路径
|
||||
//判断目录是否存在,不存在则创建该目录
|
||||
File dirFile = new File(dbDir); |
||||
if (!dirFile.exists()) { |
||||
dirFile.mkdirs(); |
||||
} |
||||
|
||||
//数据库文件是否创建成功
|
||||
boolean isFileCreateSuccess = false; |
||||
//判断文件是否存在,不存在则创建该文件
|
||||
File dbFile = new File(dbPath); |
||||
if (!dbFile.exists()) { |
||||
try { |
||||
isFileCreateSuccess = dbFile.createNewFile();//创建文件
|
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
isFileCreateSuccess = true; |
||||
} |
||||
|
||||
//返回数据库文件对象
|
||||
if (isFileCreateSuccess) { |
||||
return dbFile; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。 |
||||
*/ |
||||
@Override |
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode, |
||||
SQLiteDatabase.CursorFactory factory) { |
||||
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null); |
||||
} |
||||
|
||||
/** |
||||
* Android 4.0会调用此方法获取数据库。 |
||||
* |
||||
* @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int, |
||||
* android.database.sqlite.SQLiteDatabase.CursorFactory, |
||||
* android.database.DatabaseErrorHandler) |
||||
*/ |
||||
@Override |
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode, |
||||
SQLiteDatabase.CursorFactory factory, |
||||
DatabaseErrorHandler errorHandler) { |
||||
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null); |
||||
} |
||||
} |
@ -1,249 +0,0 @@ |
||||
/* |
||||
* 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.app.Application; |
||||
import android.content.Context; |
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.support.annotation.NonNull; |
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by lyy on 2015/2/11. |
||||
* 数据库操作工具 |
||||
*/ |
||||
public class DbUtil { |
||||
private static final String TAG = "DbUtil"; |
||||
private volatile static DbUtil INSTANCE = null; |
||||
private int ROW_ID = 7; |
||||
private SQLiteDatabase mDb; |
||||
private SqlHelper mHelper; |
||||
|
||||
private DbUtil() { |
||||
|
||||
} |
||||
|
||||
private DbUtil(Context context) { |
||||
mHelper = SqlHelper.init(context.getApplicationContext()); |
||||
} |
||||
|
||||
public static DbUtil init(Context context) { |
||||
if (context instanceof Application) { |
||||
synchronized (AriaManager.LOCK) { |
||||
if (INSTANCE == null) { |
||||
INSTANCE = new DbUtil(context); |
||||
} |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
protected static DbUtil getInstance() { |
||||
if (INSTANCE == null) { |
||||
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册"); |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
///**
|
||||
// * 关键字模糊检索全文
|
||||
// *
|
||||
// * @param column 需要查找的列
|
||||
// * @param mathSql 关键字语法,exsimple “white OR green”、“blue AND red”、“white NOT green”
|
||||
// */
|
||||
//public <T extends DbEntity> List<T> searchData(Class<T> clazz, String column, String mathSql) {
|
||||
// checkDb();
|
||||
// return SqlHelper.searchData(mDb, clazz, column, mathSql);
|
||||
//}
|
||||
|
||||
/** |
||||
* 检查某个字段的值是否存在 |
||||
* |
||||
* @param expression 字段和值"url=xxx" |
||||
* @return {@code true}该字段的对应的value已存在 |
||||
*/ |
||||
synchronized boolean checkDataExist(Class clazz, String... expression) { |
||||
checkDb(); |
||||
return SqlHelper.checkDataExist(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 清空表数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> void clean(Class<T> clazz) { |
||||
checkDb(); |
||||
String tableName = CommonUtil.getClassName(clazz); |
||||
if (tableExists(clazz)) { |
||||
String sql = "DELETE FROM " + tableName; |
||||
exeSql(sql); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 执行sql语句 |
||||
*/ |
||||
void exeSql(String sql) { |
||||
mDb.execSQL(sql); |
||||
} |
||||
|
||||
/** |
||||
* 删除某条数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> void delData(Class<T> clazz, String... expression) { |
||||
CheckUtil.checkSqlExpression(expression); |
||||
checkDb(); |
||||
SqlHelper.delData(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 修改某行数据 |
||||
*/ |
||||
synchronized void modifyData(DbEntity dbEntity) { |
||||
checkDb(); |
||||
SqlHelper.modifyData(mDb, dbEntity); |
||||
} |
||||
|
||||
/** |
||||
* 遍历所有数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> List<T> findAllData(Class<T> clazz) { |
||||
checkDb(); |
||||
return SqlHelper.findAllData(mDb, clazz); |
||||
} |
||||
|
||||
/** |
||||
* 条件查寻数据 |
||||
*/ |
||||
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, String... expression) { |
||||
checkDb(); |
||||
return SqlHelper.findData(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 通过rowId判断数据是否存在 |
||||
*/ |
||||
synchronized <T extends DbEntity> boolean isExist(Class<T> clazz, int rowId) { |
||||
checkDb(); |
||||
String sql = "SELECT rowid FROM " + CommonUtil.getClassName(clazz) + " WHERE rowid=" + rowId; |
||||
Cursor cursor = mDb.rawQuery(sql, null); |
||||
boolean isExist = cursor.getCount() > 0; |
||||
cursor.close(); |
||||
return isExist; |
||||
} |
||||
|
||||
/** |
||||
* 条件查寻数据 |
||||
*/ |
||||
@Deprecated synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, |
||||
@NonNull String[] wheres, @NonNull String[] values) { |
||||
checkDb(); |
||||
return SqlHelper.findData(mDb, clazz, wheres, values); |
||||
} |
||||
|
||||
/** |
||||
* 插入数据 |
||||
*/ |
||||
synchronized void insertData(DbEntity dbEntity) { |
||||
checkDb(); |
||||
SqlHelper.insertData(mDb, dbEntity); |
||||
} |
||||
|
||||
/** |
||||
* 查找某张表是否存在 |
||||
*/ |
||||
synchronized boolean tableExists(Class clazz) { |
||||
checkDb(); |
||||
return SqlHelper.tableExists(mDb, clazz); |
||||
} |
||||
|
||||
synchronized void createTable(Class clazz, String tableName) { |
||||
checkDb(); |
||||
SqlHelper.createTable(mDb, clazz, tableName); |
||||
} |
||||
|
||||
private void checkDb() { |
||||
if (mDb == null || !mDb.isOpen()) { |
||||
mDb = mHelper.getReadableDatabase(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 创建表 |
||||
*/ |
||||
private synchronized void createTable(Class clazz) { |
||||
createTable(clazz, null); |
||||
} |
||||
|
||||
/** |
||||
* 关闭数据库 |
||||
*/ |
||||
private synchronized void close() { |
||||
if (mDb != null) { |
||||
mDb.close(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取所在行Id |
||||
*/ |
||||
synchronized int[] getRowId(Class clazz) { |
||||
checkDb(); |
||||
Cursor cursor = mDb.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(); |
||||
return ids; |
||||
} |
||||
|
||||
/** |
||||
* 获取行Id |
||||
*/ |
||||
synchronized int getRowId(Class clazz, Object[] wheres, Object[] values) { |
||||
checkDb(); |
||||
if (wheres.length <= 0 || values.length <= 0) { |
||||
ALog.e(TAG, "请输入删除条件"); |
||||
return -1; |
||||
} else if (wheres.length != values.length) { |
||||
ALog.e(TAG, "groupName 和 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++; |
||||
} |
||||
SqlHelper.print(ROW_ID, sb.toString()); |
||||
Cursor c = mDb.rawQuery(sb.toString(), null); |
||||
int id = c.getColumnIndex("rowid"); |
||||
c.close(); |
||||
close(); |
||||
return id; |
||||
} |
||||
} |
@ -0,0 +1,221 @@ |
||||
/* |
||||
* 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.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.orm.annotation.Default; |
||||
import com.arialyy.aria.orm.annotation.Foreign; |
||||
import com.arialyy.aria.orm.annotation.Primary; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.lang.reflect.Field; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* 通用委托,创建表,检查字段 |
||||
*/ |
||||
class DelegateCommon extends AbsDelegate { |
||||
private DelegateCommon() { |
||||
} |
||||
|
||||
/** |
||||
* 删除指定的表 |
||||
*/ |
||||
void dropTable(SQLiteDatabase db, String tableName) { |
||||
db = checkDb(db); |
||||
String deleteSQL = "DROP TABLE IF EXISTS ".concat(tableName); |
||||
print(DROP_TABLE, deleteSQL); |
||||
//db.beginTransaction();
|
||||
db.execSQL(deleteSQL); |
||||
//db.setTransactionSuccessful();
|
||||
//db.endTransaction();
|
||||
} |
||||
|
||||
/** |
||||
* 清空表数据 |
||||
*/ |
||||
<T extends DbEntity> void clean(SQLiteDatabase db, Class<T> clazz) { |
||||
db = checkDb(db); |
||||
String tableName = CommonUtil.getClassName(clazz); |
||||
if (tableExists(db, clazz)) { |
||||
String sql = "DELETE FROM " + tableName; |
||||
db.execSQL(sql); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 查找表是否存在 |
||||
* |
||||
* @param clazz 数据库实体 |
||||
* @return true,该数据库实体对应的表存在;false,不存在 |
||||
*/ |
||||
boolean tableExists(SQLiteDatabase db, Class clazz) { |
||||
return tableExists(db, CommonUtil.getClassName(clazz)); |
||||
} |
||||
|
||||
private boolean tableExists(SQLiteDatabase db, String tableName) { |
||||
db = checkDb(db); |
||||
Cursor cursor = null; |
||||
try { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='"); |
||||
sb.append(tableName); |
||||
sb.append("'"); |
||||
print(TABLE_EXISTS, sb.toString()); |
||||
cursor = db.rawQuery(sb.toString(), null); |
||||
if (cursor != null && cursor.moveToNext()) { |
||||
int count = cursor.getInt(0); |
||||
if (count > 0) { |
||||
return true; |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} finally { |
||||
closeCursor(cursor); |
||||
close(db); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 检查某个字段的值是否存在 |
||||
* |
||||
* @param expression 字段和值"url=xxx" |
||||
* @return {@code true}该字段的对应的value已存在 |
||||
*/ |
||||
boolean checkDataExist(SQLiteDatabase db, Class clazz, String... expression) { |
||||
db = checkDb(db); |
||||
CheckUtil.checkSqlExpression(expression); |
||||
String sql = |
||||
"SELECT rowid, * FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " "; |
||||
sql = sql.replace("?", "%s"); |
||||
Object[] params = new String[expression.length - 1]; |
||||
for (int i = 0, len = params.length; i < len; i++) { |
||||
params[i] = "'" + expression[i + 1] + "'"; |
||||
} |
||||
sql = String.format(sql, params); |
||||
print(FIND_DATA, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
final boolean isExist = cursor.getCount() > 0; |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return isExist; |
||||
} |
||||
|
||||
/** |
||||
* 创建表 |
||||
* |
||||
* @param clazz 数据库实体 |
||||
*/ |
||||
void createTable(SQLiteDatabase db, Class clazz) { |
||||
db = checkDb(db); |
||||
List<Field> fields = CommonUtil.getAllFields(clazz); |
||||
if (fields != null && fields.size() > 0) { |
||||
//外键Map,在Sqlite3中foreign修饰的字段必须放在最后
|
||||
final List<Field> foreignArray = new ArrayList<>(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("CREATE TABLE ") |
||||
.append(CommonUtil.getClassName(clazz)) |
||||
.append(" ("); |
||||
for (Field field : fields) { |
||||
field.setAccessible(true); |
||||
if (SqlUtil.isIgnore(field)) { |
||||
continue; |
||||
} |
||||
Class<?> type = field.getType(); |
||||
sb.append(field.getName()); |
||||
if (type == String.class || type.isEnum()) { |
||||
sb.append(" VARCHAR"); |
||||
} else if (type == int.class || type == Integer.class) { |
||||
sb.append(" INTEGER"); |
||||
} else if (type == float.class || type == Float.class) { |
||||
sb.append(" FLOAT"); |
||||
} else if (type == double.class || type == Double.class) { |
||||
sb.append(" DOUBLE"); |
||||
} else if (type == long.class || type == Long.class) { |
||||
sb.append(" BIGINT"); |
||||
} else if (type == boolean.class || type == Boolean.class) { |
||||
sb.append(" BOOLEAN"); |
||||
} else if (type == java.util.Date.class || type == java.sql.Date.class) { |
||||
sb.append(" DATA"); |
||||
} else if (type == byte.class || type == Byte.class) { |
||||
sb.append(" BLOB"); |
||||
} else if (type == Map.class || type == List.class) { |
||||
sb.append(" TEXT"); |
||||
} else { |
||||
continue; |
||||
} |
||||
if (SqlUtil.isPrimary(field)) { |
||||
Primary pk = field.getAnnotation(Primary.class); |
||||
sb.append(" PRIMARY KEY"); |
||||
if (pk.autoincrement() && (type == int.class || type == Integer.class)) { |
||||
sb.append(" AUTOINCREMENT"); |
||||
} |
||||
} |
||||
|
||||
if (SqlUtil.isForeign(field)) { |
||||
foreignArray.add(field); |
||||
} |
||||
|
||||
if (SqlUtil.isNoNull(field)) { |
||||
sb.append(" NOT NULL"); |
||||
} |
||||
|
||||
if (SqlUtil.isDefault(field)) { |
||||
Default d = field.getAnnotation(Default.class); |
||||
if (!TextUtils.isEmpty(d.value())) { |
||||
sb.append(" DEFAULT ").append("'").append(d.value()).append("'"); |
||||
} |
||||
} |
||||
|
||||
sb.append(","); |
||||
} |
||||
|
||||
for (Field field : foreignArray) { |
||||
Foreign foreign = field.getAnnotation(Foreign.class); |
||||
sb.append("FOREIGN KEY (") |
||||
.append(field.getName()) |
||||
.append(") REFERENCES ") |
||||
.append(CommonUtil.getClassName(foreign.parent())) |
||||
.append("(") |
||||
.append(foreign.column()) |
||||
.append(")"); |
||||
ActionPolicy update = foreign.onUpdate(); |
||||
ActionPolicy delete = foreign.onDelete(); |
||||
if (update != ActionPolicy.NO_ACTION) { |
||||
sb.append(" ON UPDATE ").append(update.function); |
||||
} |
||||
|
||||
if (delete != ActionPolicy.NO_ACTION) { |
||||
sb.append(" ON DELETE ").append(update.function); |
||||
} |
||||
sb.append(","); |
||||
} |
||||
|
||||
String str = sb.toString(); |
||||
str = str.substring(0, str.length() - 1) + ");"; |
||||
print(CREATE_TABLE, str); |
||||
db.execSQL(str); |
||||
} |
||||
close(db); |
||||
} |
||||
} |
@ -0,0 +1,512 @@ |
||||
/* |
||||
* 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.Date; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.WeakHashMap; |
||||
|
||||
/** |
||||
* 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 Wrapper}注解,将返回null |
||||
* 如果实体中没有{@link One}或{@link Many}注解,将返回null |
||||
* 如果实体中有多个{@link One}或{@link Many}注解,将返回nul |
||||
*/ |
||||
<T extends AbsWrapper> List<T> findRelationData(SQLiteDatabase db, Class<T> clazz, |
||||
String... expression) { |
||||
db = checkDb(db); |
||||
|
||||
if (SqlUtil.isWrapper(clazz)) { |
||||
StringBuilder sb = new StringBuilder(); |
||||
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; |
||||
} |
||||
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; |
||||
} |
||||
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<Field> pColumn = SqlUtil.getAllNotIgnoreField(parentClazz); |
||||
List<Field> cColumn = SqlUtil.getAllNotIgnoreField(childClazz); |
||||
List<String> pColumnAlias = new ArrayList<>(); |
||||
List<String> 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] = "'" + convertValue(expression[i + 1]) + "'"; |
||||
} |
||||
sql = String.format(sql, params); |
||||
} else { |
||||
sql = sb.toString(); |
||||
} |
||||
print(RELATION, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
List<T> data = |
||||
(List<T>) newInstanceEntity(clazz, parentClazz, childClazz, cursor, pColumn, cColumn, |
||||
pColumnAlias, cColumnAlias); |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return data; |
||||
} catch (ClassNotFoundException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} else { |
||||
ALog.w(TAG, "查询数据失败,实体类没有使用@Wrapper 注解"); |
||||
return null; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* 创建关联查询的数据 |
||||
* |
||||
* @param pColumn 父表的所有字段 |
||||
* @param cColumn 字表的所有字段 |
||||
* @param pColumnAlias 关联查询父表别名 |
||||
* @param cColumnAlias 关联查询子表别名 |
||||
*/ |
||||
private <T extends AbsWrapper, P extends DbEntity, C extends DbEntity> List<T> newInstanceEntity( |
||||
Class<T> clazz, Class<P> parent, |
||||
Class<C> child, |
||||
Cursor cursor, |
||||
List<Field> pColumn, List<Field> cColumn, |
||||
List<String> pColumnAlias, List<String> cColumnAlias) { |
||||
try { |
||||
String parentPrimary = ""; //父表主键别名
|
||||
for (Field f : pColumn) { |
||||
if (SqlUtil.isPrimary(f)) { |
||||
parentPrimary = PARENT_COLUMN_ALIAS.concat(f.getName()); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
List<T> wrappers = new ArrayList<>(); |
||||
Map<Object, P> tempParent = new WeakHashMap<>(); // 所有父表元素,key为父表主键的值
|
||||
Map<Object, List<C>> tempChild = new WeakHashMap<>(); // 所有的字表元素,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<C>()); |
||||
} |
||||
tempChild.get(old).add(cEntity); |
||||
} |
||||
|
||||
List<Field> wFields = SqlUtil.getAllNotIgnoreField(clazz); |
||||
if (wFields != null && !wFields.isEmpty()) { |
||||
Set<Object> 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; |
||||
} |
||||
|
||||
/** |
||||
* 条件查寻数据 |
||||
*/ |
||||
<T extends DbEntity> List<T> findData(SQLiteDatabase db, Class<T> clazz, String... expression) { |
||||
db = checkDb(db); |
||||
CheckUtil.checkSqlExpression(expression); |
||||
String sql = |
||||
"SELECT rowid, * FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " "; |
||||
sql = sql.replace("?", "%s"); |
||||
Object[] params = new String[expression.length - 1]; |
||||
for (int i = 0, len = params.length; i < len; i++) { |
||||
params[i] = "'" + convertValue(expression[i + 1]) + "'"; |
||||
} |
||||
sql = String.format(sql, params); |
||||
print(FIND_DATA, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* 查找表的所有数据 |
||||
*/ |
||||
<T extends DbEntity> List<T> findAllData(SQLiteDatabase db, Class<T> clazz) { |
||||
db = checkDb(db); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("SELECT rowid, * FROM ").append(CommonUtil.getClassName(clazz)); |
||||
print(FIND_ALL_DATA, sb.toString()); |
||||
Cursor cursor = db.rawQuery(sb.toString(), null); |
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; |
||||
closeCursor(cursor); |
||||
close(db); |
||||
return data; |
||||
} |
||||
|
||||
/** |
||||
* 根据数据游标创建一个具体的对象 |
||||
*/ |
||||
private <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz, Cursor cursor) { |
||||
List<Field> fields = CommonUtil.getAllFields(clazz); |
||||
List<T> 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 (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(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(temp)); |
||||
} |
||||
} else if (type == List.class) { |
||||
String value = cursor.getString(column); |
||||
if (!TextUtils.isEmpty(value)) { |
||||
field.set(entity, SqlUtil.str2List(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, "groupName 和 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判断数据是否存在 |
||||
*/ |
||||
<T extends DbEntity> boolean itemExist(SQLiteDatabase db, Class<T> clazz, |
||||
int rowId) { |
||||
db = checkDb(db); |
||||
String sql = "SELECT rowid FROM " + CommonUtil.getClassName(clazz) + " WHERE rowid=" + rowId; |
||||
print(ROW_ID, sql); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
boolean isExist = cursor.getCount() > 0; |
||||
cursor.close(); |
||||
return isExist; |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
/* |
||||
* 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.util.SparseArray; |
||||
import java.lang.reflect.Constructor; |
||||
import java.lang.reflect.InvocationTargetException; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* Delegate管理器 |
||||
*/ |
||||
class DelegateManager { |
||||
private final String TAG = "ModuleFactory"; |
||||
|
||||
private SparseArray<AbsDelegate> mDelegates = new SparseArray<>(); |
||||
private static volatile DelegateManager INSTANCE = null; |
||||
|
||||
private DelegateManager() { |
||||
|
||||
} |
||||
|
||||
static DelegateManager getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (DelegateManager.class) { |
||||
INSTANCE = new DelegateManager(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* 获取Module |
||||
*/ |
||||
<M extends AbsDelegate> M getDelegate(Class<M> clazz) { |
||||
M delegate = (M) mDelegates.get(clazz.hashCode()); |
||||
try { |
||||
if (delegate == null) { |
||||
Constructor c = clazz.getDeclaredConstructor(); |
||||
c.setAccessible(true); |
||||
delegate = (M) c.newInstance(); |
||||
mDelegates.put(clazz.hashCode(), delegate); |
||||
return delegate; |
||||
} |
||||
} catch (InstantiationException e) { |
||||
e.printStackTrace(); |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} catch (NoSuchMethodException e) { |
||||
e.printStackTrace(); |
||||
} catch (InvocationTargetException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return delegate; |
||||
} |
||||
} |
@ -0,0 +1,186 @@ |
||||
/* |
||||
* 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.database.sqlite.SQLiteDatabase; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.orm.annotation.Primary; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Type; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* 增加数据、更新数据 |
||||
*/ |
||||
class DelegateUpdate extends AbsDelegate { |
||||
private DelegateUpdate() { |
||||
} |
||||
|
||||
/** |
||||
* 删除某条数据 |
||||
*/ |
||||
<T extends DbEntity> void delData(SQLiteDatabase db, Class<T> clazz, String... expression) { |
||||
db = checkDb(db); |
||||
CheckUtil.checkSqlExpression(expression); |
||||
|
||||
String sql = "DELETE FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " "; |
||||
sql = sql.replace("?", "%s"); |
||||
Object[] params = new String[expression.length - 1]; |
||||
for (int i = 0, len = params.length; i < len; i++) { |
||||
params[i] = "'" + expression[i + 1] + "'"; |
||||
} |
||||
sql = String.format(sql, params); |
||||
print(DEL_DATA, sql); |
||||
db.execSQL(sql); |
||||
close(db); |
||||
} |
||||
|
||||
/** |
||||
* 修改某行数据 |
||||
*/ |
||||
void modifyData(SQLiteDatabase db, DbEntity dbEntity) { |
||||
db = checkDb(db); |
||||
Class<?> clazz = dbEntity.getClass(); |
||||
List<Field> fields = CommonUtil.getAllFields(clazz); |
||||
DbEntity cacheEntity = mDataCache.get(getCacheKey(dbEntity)); |
||||
if (fields != null && fields.size() > 0) { |
||||
StringBuilder sql = new StringBuilder(); |
||||
StringBuilder prams = new StringBuilder(); |
||||
sql.append("UPDATE ").append(CommonUtil.getClassName(dbEntity)).append(" SET "); |
||||
int i = 0; |
||||
try { |
||||
for (Field field : fields) { |
||||
field.setAccessible(true); |
||||
if (isIgnore(dbEntity, field)) { |
||||
continue; |
||||
} |
||||
if (cacheEntity != null |
||||
&& field.get(dbEntity) == field.get(cacheEntity) |
||||
&& !field.getName().equals("state")) { //在LruCache中 state字段总是不能重新赋值...
|
||||
continue; |
||||
} |
||||
|
||||
String value; |
||||
prams.append(i > 0 ? ", " : ""); |
||||
prams.append(field.getName()).append("='"); |
||||
Type type = field.getType(); |
||||
if (type == Map.class && checkMap(field)) { |
||||
value = SqlUtil.map2Str((Map<String, String>) field.get(dbEntity)); |
||||
} else if (type == List.class && checkList(field)) { |
||||
value = SqlUtil.list2Str(dbEntity, field); |
||||
} else { |
||||
Object obj = field.get(dbEntity); |
||||
value = obj == null ? "" : convertValue(obj.toString()); |
||||
} |
||||
|
||||
prams.append(TextUtils.isEmpty(value) ? "" : value); |
||||
prams.append("'"); |
||||
i++; |
||||
} |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
if (!TextUtils.isEmpty(prams.toString())) { |
||||
sql.append(prams.toString()); |
||||
sql.append(" where rowid=").append(dbEntity.rowID); |
||||
print(MODIFY_DATA, sql.toString()); |
||||
db.execSQL(sql.toString()); |
||||
} |
||||
} |
||||
mDataCache.put(getCacheKey(dbEntity), dbEntity); |
||||
close(db); |
||||
} |
||||
|
||||
/** |
||||
* 插入数据 |
||||
*/ |
||||
void insertData(SQLiteDatabase db, DbEntity dbEntity) { |
||||
db = checkDb(db); |
||||
Class<?> clazz = dbEntity.getClass(); |
||||
List<Field> fields = CommonUtil.getAllFields(clazz); |
||||
if (fields != null && fields.size() > 0) { |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("INSERT INTO ").append(CommonUtil.getClassName(dbEntity)).append("("); |
||||
int i = 0; |
||||
try { |
||||
for (Field field : fields) { |
||||
field.setAccessible(true); |
||||
if (isIgnore(dbEntity, field)) { |
||||
continue; |
||||
} |
||||
sb.append(i > 0 ? ", " : ""); |
||||
sb.append(field.getName()); |
||||
i++; |
||||
} |
||||
sb.append(") VALUES ("); |
||||
i = 0; |
||||
for (Field field : fields) { |
||||
field.setAccessible(true); |
||||
if (isIgnore(dbEntity, field)) { |
||||
continue; |
||||
} |
||||
sb.append(i > 0 ? ", " : ""); |
||||
sb.append("'"); |
||||
Type type = field.getType(); |
||||
if (type == Map.class && checkMap(field)) { |
||||
sb.append(SqlUtil.map2Str((Map<String, String>) field.get(dbEntity))); |
||||
} else if (type == List.class && checkList(field)) { |
||||
sb.append(SqlUtil.list2Str(dbEntity, field)); |
||||
} else { |
||||
Object obj = field.get(dbEntity); |
||||
if (obj != null) { |
||||
sb.append(convertValue(field.get(dbEntity).toString())); |
||||
} |
||||
} |
||||
sb.append("'"); |
||||
i++; |
||||
} |
||||
} catch (IllegalAccessException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
sb.append(")"); |
||||
print(INSERT_DATA, sb.toString()); |
||||
db.execSQL(sb.toString()); |
||||
} |
||||
close(db); |
||||
} |
||||
|
||||
/** |
||||
* {@code true}自动增长的主键和需要忽略的字段 |
||||
*/ |
||||
private boolean isIgnore(Object obj, Field field) throws IllegalAccessException { |
||||
if (SqlUtil.isIgnore(field)) { |
||||
return true; |
||||
} |
||||
if (SqlUtil.isPrimary(field)) { //忽略自动增长的主键
|
||||
Primary p = field.getAnnotation(Primary.class); |
||||
if (p.autoincrement()) { |
||||
return true; |
||||
} |
||||
} |
||||
if (SqlUtil.isForeign(field)) { //忽略外键为null的字段
|
||||
Object value = field.get(obj); |
||||
if (value == null || (value instanceof String && TextUtils.isEmpty(String.valueOf(value)))) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,155 @@ |
||||
/* |
||||
* 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 android.database.sqlite.SQLiteDatabase; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by lyy on 2015/2/11. |
||||
* 数据库操作工具 |
||||
*/ |
||||
public class DelegateWrapper { |
||||
private static final String TAG = "DelegateWrapper"; |
||||
private volatile static DelegateWrapper INSTANCE = null; |
||||
|
||||
private SQLiteDatabase mDb; |
||||
private DelegateManager mDManager; |
||||
|
||||
private DelegateWrapper() { |
||||
|
||||
} |
||||
|
||||
private DelegateWrapper(Context context) { |
||||
SqlHelper helper = SqlHelper.init(context.getApplicationContext()); |
||||
mDb = helper.getWritableDatabase(); |
||||
mDManager = DelegateManager.getInstance(); |
||||
} |
||||
|
||||
public static void init(Context context) { |
||||
synchronized (DelegateWrapper.class) { |
||||
if (INSTANCE == null) { |
||||
INSTANCE = new DelegateWrapper(context); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static DelegateWrapper getInstance() { |
||||
if (INSTANCE == null) { |
||||
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册"); |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* 查询关联表数据 |
||||
* |
||||
* @param expression 查询条件 |
||||
*/ |
||||
<T extends AbsWrapper> List<T> findRelationData(Class<T> clazz, String... expression) { |
||||
return mDManager.getDelegate(DelegateFind.class).findRelationData(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 检查某个字段的值是否存在 |
||||
* |
||||
* @param expression 字段和值"url=xxx" |
||||
* @return {@code true}该字段的对应的value已存在 |
||||
*/ |
||||
boolean checkDataExist(Class clazz, String... expression) { |
||||
return mDManager.getDelegate(DelegateCommon.class) |
||||
.checkDataExist(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 清空表数据 |
||||
*/ |
||||
<T extends DbEntity> void clean(Class<T> clazz) { |
||||
mDManager.getDelegate(DelegateCommon.class).clean(mDb, clazz); |
||||
} |
||||
|
||||
/** |
||||
* 执行sql语句 |
||||
*/ |
||||
void exeSql(String sql) { |
||||
mDb.execSQL(sql); |
||||
} |
||||
|
||||
/** |
||||
* 删除某条数据 |
||||
*/ |
||||
<T extends DbEntity> void delData(Class<T> clazz, String... expression) { |
||||
mDManager.getDelegate(DelegateUpdate.class).delData(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 修改某行数据 |
||||
*/ |
||||
void modifyData(DbEntity dbEntity) { |
||||
mDManager.getDelegate(DelegateUpdate.class).modifyData(mDb, dbEntity); |
||||
} |
||||
|
||||
/** |
||||
* 遍历所有数据 |
||||
*/ |
||||
<T extends DbEntity> List<T> findAllData(Class<T> clazz) { |
||||
return mDManager.getDelegate(DelegateFind.class).findAllData(mDb, clazz); |
||||
} |
||||
|
||||
/** |
||||
* 条件查寻数据 |
||||
*/ |
||||
<T extends DbEntity> List<T> findData(Class<T> clazz, String... expression) { |
||||
return mDManager.getDelegate(DelegateFind.class).findData(mDb, clazz, expression); |
||||
} |
||||
|
||||
/** |
||||
* 通过rowId判断数据是否存在 |
||||
*/ |
||||
<T extends DbEntity> boolean isExist(Class<T> clazz, int rowId) { |
||||
return mDManager.getDelegate(DelegateFind.class).itemExist(mDb, clazz, rowId); |
||||
} |
||||
|
||||
/** |
||||
* 插入数据 |
||||
*/ |
||||
void insertData(DbEntity dbEntity) { |
||||
mDManager.getDelegate(DelegateUpdate.class).insertData(mDb, dbEntity); |
||||
} |
||||
|
||||
/** |
||||
* 查找某张表是否存在 |
||||
*/ |
||||
boolean tableExists(Class clazz) { |
||||
return mDManager.getDelegate(DelegateCommon.class).tableExists(mDb, clazz); |
||||
} |
||||
|
||||
/** |
||||
* 获取所在行Id |
||||
*/ |
||||
int[] getRowId(Class clazz) { |
||||
return mDManager.getDelegate(DelegateFind.class).getRowId(mDb, clazz); |
||||
} |
||||
|
||||
/** |
||||
* 获取行Id |
||||
*/ |
||||
int getRowId(Class clazz, Object[] wheres, Object[] values) { |
||||
return mDManager.getDelegate(DelegateFind.class).getRowId(mDb, clazz, wheres, values); |
||||
} |
||||
} |
@ -1,32 +0,0 @@ |
||||
/* |
||||
* 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 java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* Created by AriaL on 2017/7/4. |
||||
* 基本类型的List,只能用于常见的数据类型,如果是一对多的复杂数据结构,需要使用{@link OneToMany} |
||||
*/ |
||||
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface NormalList { |
||||
/** |
||||
* 数据类型 |
||||
*/ |
||||
Class clazz(); |
||||
} |
@ -0,0 +1,50 @@ |
||||
/* |
||||
* 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.annotation; |
||||
|
||||
import com.arialyy.aria.orm.ActionPolicy; |
||||
import com.arialyy.aria.orm.DbEntity; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* Created by AriaL on 2017/7/4. |
||||
* 外键约束 |
||||
*/ |
||||
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Foreign { |
||||
|
||||
/** |
||||
* 关联的表 |
||||
*/ |
||||
Class<? extends DbEntity> parent(); |
||||
|
||||
/** |
||||
* 父表对应的列名 |
||||
*/ |
||||
String column(); |
||||
|
||||
/** |
||||
* ON UPDATE 约束 |
||||
*/ |
||||
ActionPolicy onUpdate() default ActionPolicy.NO_ACTION; |
||||
|
||||
/** |
||||
* ON DELETE 约束 |
||||
*/ |
||||
ActionPolicy onDelete() default ActionPolicy.NO_ACTION; |
||||
} |
@ -0,0 +1,30 @@ |
||||
/* |
||||
* 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.annotation; |
||||
|
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* Created by lyy on 2015/11/2. |
||||
* 设置表名,如果不是使用该注解,默认为类名 |
||||
*/ |
||||
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Table { |
||||
String tableName(); |
||||
} |
Loading…
Reference in new issue