优化数据库写入\修改的速度
This commit is contained in:
@@ -18,10 +18,13 @@ package com.arialyy.aria.core.download;
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.manager.SubTaskManager;
|
||||
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -122,6 +125,9 @@ abstract class BaseGroupTarget<TARGET extends BaseGroupTarget>
|
||||
void reChangeDirPath(String newDirPath) {
|
||||
List<DownloadTaskEntity> subTasks = mTaskEntity.getSubTaskEntities();
|
||||
if (subTasks != null && !subTasks.isEmpty()) {
|
||||
//List<DownloadEntity> des = new ArrayList<>();
|
||||
//List<DownloadTaskEntity> dtes = new ArrayList<>();
|
||||
List<DbEntity> des = new ArrayList<>();
|
||||
for (DownloadTaskEntity dte : subTasks) {
|
||||
DownloadEntity de = dte.getEntity();
|
||||
String oldPath = de.getDownloadPath();
|
||||
@@ -132,9 +138,15 @@ abstract class BaseGroupTarget<TARGET extends BaseGroupTarget>
|
||||
}
|
||||
de.setDownloadPath(newPath);
|
||||
dte.setKey(newPath);
|
||||
de.save();
|
||||
dte.save();
|
||||
|
||||
//des.add(de);
|
||||
//dtes.add(dte);
|
||||
//de.save();
|
||||
//dte.save();
|
||||
des.add(de);
|
||||
des.add(dte);
|
||||
}
|
||||
AbsEntity.saveAll(des);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
package com.arialyy.aria.orm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/11/2.
|
||||
* 所有数据库实体父类
|
||||
* Created by lyy on 2015/11/2. 所有数据库实体父类
|
||||
*/
|
||||
public abstract class DbEntity {
|
||||
private static final Object LOCK = new Object();
|
||||
@@ -129,6 +129,57 @@ public abstract class DbEntity {
|
||||
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入多条数据
|
||||
*/
|
||||
public static void insertManyData(List<DbEntity> entities) {
|
||||
checkListData(entities);
|
||||
DelegateWrapper.getInstance().insertManyData(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改多条数据
|
||||
*/
|
||||
public static void updateManyData(List<DbEntity> entities) {
|
||||
checkListData(entities);
|
||||
DelegateWrapper.getInstance().updateManyData(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存多条数据,通过rowID来判断记录存在以否,如果数据库已有记录,则更新该记录;如果数据库中没有记录,则保存该记录
|
||||
*/
|
||||
public static void saveAll(List<DbEntity> entities) {
|
||||
checkListData(entities);
|
||||
List<DbEntity> insertD = new ArrayList<>();
|
||||
List<DbEntity> updateD = new ArrayList<>();
|
||||
DelegateWrapper wrapper = DelegateWrapper.getInstance();
|
||||
for (DbEntity entity : entities) {
|
||||
if (entity.rowID == -1) {
|
||||
insertD.add(entity);
|
||||
continue;
|
||||
}
|
||||
if (wrapper.isExist(entity.getClass(), entity.rowID)) {
|
||||
insertD.add(entity);
|
||||
} else {
|
||||
updateD.add(entity);
|
||||
}
|
||||
}
|
||||
if (!insertD.isEmpty()) {
|
||||
wrapper.insertManyData(insertD);
|
||||
} else {
|
||||
wrapper.updateManyData(updateD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查批量操作的列表数据,如果数据为空,抛出{@link NullPointerException}
|
||||
*/
|
||||
private static void checkListData(List<DbEntity> entities) {
|
||||
if (entities == null || entities.isEmpty()) {
|
||||
throw new NullPointerException("列表数据为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除当前数据
|
||||
*/
|
||||
@@ -151,12 +202,11 @@ public abstract class DbEntity {
|
||||
* 修改数据
|
||||
*/
|
||||
public void update() {
|
||||
DelegateWrapper.getInstance().modifyData(this);
|
||||
DelegateWrapper.getInstance().updateData(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存自身,如果表中已经有数据,则更新数据,否则插入数据
|
||||
* 只有 target中checkEntity成功后才能保存,创建实体部分也不允许保存
|
||||
* 保存自身,如果表中已经有数据,则更新数据,否则插入数据 只有 target中checkEntity成功后才能保存,创建实体部分也不允许保存
|
||||
*/
|
||||
public void save() {
|
||||
synchronized (LOCK) {
|
||||
@@ -178,9 +228,10 @@ public abstract class DbEntity {
|
||||
|
||||
/**
|
||||
* 表是否存在
|
||||
* @return {@code true} 存在
|
||||
*
|
||||
* @return {@code true} 存在
|
||||
*/
|
||||
public static boolean tableExists(Class<DbEntity> clazz){
|
||||
public static boolean tableExists(Class<DbEntity> clazz) {
|
||||
return DelegateWrapper.getInstance().tableExists(clazz);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by laoyuyu on 2018/3/22.
|
||||
* 增加数据、更新数据
|
||||
* Created by laoyuyu on 2018/3/22. 增加数据、更新数据
|
||||
*/
|
||||
class DelegateUpdate extends AbsDelegate {
|
||||
private DelegateUpdate() {
|
||||
@@ -82,7 +81,8 @@ class DelegateUpdate extends AbsDelegate {
|
||||
/**
|
||||
* 删除某条数据
|
||||
*/
|
||||
synchronized <T extends DbEntity> void delData(SQLiteDatabase db, Class<T> clazz, String... expression) {
|
||||
synchronized <T extends DbEntity> void delData(SQLiteDatabase db, Class<T> clazz,
|
||||
String... expression) {
|
||||
db = checkDb(db);
|
||||
CheckUtil.checkSqlExpression(expression);
|
||||
|
||||
@@ -101,50 +101,98 @@ class DelegateUpdate extends AbsDelegate {
|
||||
/**
|
||||
* 修改某行数据
|
||||
*/
|
||||
synchronized void modifyData(SQLiteDatabase db, DbEntity dbEntity) {
|
||||
synchronized void updateData(SQLiteDatabase db, DbEntity dbEntity) {
|
||||
db = checkDb(db);
|
||||
Class<?> clazz = dbEntity.getClass();
|
||||
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||
if (fields != null && fields.size() > 0) {
|
||||
ContentValues values = new ContentValues();
|
||||
try {
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (isIgnore(dbEntity, field)) {
|
||||
continue;
|
||||
}
|
||||
String value;
|
||||
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 ? "" : obj.toString();
|
||||
}
|
||||
values.put(field.getName(), encodeStr(value));
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (values.size() > 0) {
|
||||
db.update(CommonUtil.getClassName(dbEntity), values, "rowid=?",
|
||||
new String[] { String.valueOf(dbEntity.rowID) });
|
||||
} else {
|
||||
ALog.d(TAG, "没有数据更新");
|
||||
}
|
||||
ContentValues values = createValues(dbEntity);
|
||||
if (values != null) {
|
||||
db.update(CommonUtil.getClassName(dbEntity), values, "rowid=?",
|
||||
new String[] {String.valueOf(dbEntity.rowID)});
|
||||
} else {
|
||||
ALog.e(TAG, "更新记录失败,记录没有属性字段");
|
||||
}
|
||||
close(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新多条记录
|
||||
*/
|
||||
synchronized void updateManyData(SQLiteDatabase db, List<DbEntity> dbEntities) {
|
||||
db = checkDb(db);
|
||||
db.beginTransaction();
|
||||
try {
|
||||
Class oldClazz = null;
|
||||
String table = null;
|
||||
for (DbEntity entity : dbEntities) {
|
||||
if (oldClazz == null || oldClazz != entity.getClass() || table == null) {
|
||||
oldClazz = entity.getClass();
|
||||
table = CommonUtil.getClassName(oldClazz);
|
||||
}
|
||||
ContentValues value = createValues(entity);
|
||||
if (value == null) {
|
||||
ALog.e(TAG, "更新记录失败,记录没有属性字段");
|
||||
} else {
|
||||
db.update(table, value, "rowid=?", new String[] {String.valueOf(entity.rowID)});
|
||||
}
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入多条记录
|
||||
*/
|
||||
synchronized <T extends DbEntity> void insertManyData(SQLiteDatabase db, List<T> dbEntities) {
|
||||
db = checkDb(db);
|
||||
db.beginTransaction();
|
||||
try {
|
||||
Class oldClazz = null;
|
||||
String table = null;
|
||||
for (DbEntity entity : dbEntities) {
|
||||
if (oldClazz == null || oldClazz != entity.getClass() || table == null) {
|
||||
oldClazz = entity.getClass();
|
||||
table = CommonUtil.getClassName(oldClazz);
|
||||
}
|
||||
|
||||
ContentValues value = createValues(entity);
|
||||
if (value == null) {
|
||||
ALog.e(TAG, "保存记录失败,记录没有属性字段");
|
||||
} else {
|
||||
entity.rowID = db.insert(table, null, value);
|
||||
}
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入数据
|
||||
*/
|
||||
synchronized void insertData(SQLiteDatabase db, DbEntity dbEntity) {
|
||||
db = checkDb(db);
|
||||
Class<?> clazz = dbEntity.getClass();
|
||||
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||
ContentValues values = createValues(dbEntity);
|
||||
if (values != null) {
|
||||
dbEntity.rowID = db.insert(CommonUtil.getClassName(dbEntity), null, values);
|
||||
} else {
|
||||
ALog.e(TAG, "保存记录失败,记录没有属性字段");
|
||||
}
|
||||
close(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建存储数据\更新数据时使用的ContentValues
|
||||
*
|
||||
* @return 如果没有字段属性,返回null
|
||||
*/
|
||||
private ContentValues createValues(DbEntity dbEntity) {
|
||||
List<Field> fields = CommonUtil.getAllFields(dbEntity.getClass());
|
||||
if (fields != null && fields.size() > 0) {
|
||||
ContentValues values = new ContentValues();
|
||||
try {
|
||||
@@ -167,12 +215,12 @@ class DelegateUpdate extends AbsDelegate {
|
||||
}
|
||||
values.put(field.getName(), encodeStr(value));
|
||||
}
|
||||
return values;
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
dbEntity.rowID = db.insert(CommonUtil.getClassName(dbEntity), null, values);
|
||||
}
|
||||
close(db);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,8 +21,7 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/2/11.
|
||||
* 数据库操作工具
|
||||
* Created by lyy on 2015/2/11. 数据库操作工具
|
||||
*/
|
||||
public class DelegateWrapper {
|
||||
private static final String TAG = "DelegateWrapper";
|
||||
@@ -100,8 +99,15 @@ public class DelegateWrapper {
|
||||
/**
|
||||
* 修改某行数据
|
||||
*/
|
||||
void modifyData(DbEntity dbEntity) {
|
||||
mDManager.getDelegate(DelegateUpdate.class).modifyData(mDb, dbEntity);
|
||||
void updateData(DbEntity dbEntity) {
|
||||
mDManager.getDelegate(DelegateUpdate.class).updateData(mDb, dbEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新多条数据
|
||||
*/
|
||||
void updateManyData(List<DbEntity> dbEntitys) {
|
||||
mDManager.getDelegate(DelegateUpdate.class).updateManyData(mDb, dbEntitys);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,6 +152,13 @@ public class DelegateWrapper {
|
||||
mDManager.getDelegate(DelegateUpdate.class).insertData(mDb, dbEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入多条数据
|
||||
*/
|
||||
void insertManyData(List<DbEntity> dbEntitys) {
|
||||
mDManager.getDelegate(DelegateUpdate.class).insertManyData(mDb, dbEntitys);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找某张表是否存在
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
## 开发日志
|
||||
+ v_3.5.4
|
||||
+ v_3.5.5
|
||||
- 优化数据库写入\修改的速度
|
||||
+ v_3.5.4 (2019/1/8)
|
||||
- 修复不支持断点的下载地址,重复下载出现的数据库主键冲突问题
|
||||
+ v_3.5.3 (2018/12/23)
|
||||
- 修复ftps不能加载默认证书的bug https://github.com/AriaLyy/Aria/issues/334
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<!--android:name=".download.group.DownloadGroupActivity"-->
|
||||
<!--android:name=".MainActivity"-->
|
||||
<activity
|
||||
android:name=".download.SingleTaskActivity"
|
||||
android:name=".DbTestActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
76
app/src/main/java/com/arialyy/simple/DbTestActivity.java
Normal file
76
app/src/main/java/com/arialyy/simple/DbTestActivity.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package com.arialyy.simple;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.simple.base.BaseActivity;
|
||||
import com.arialyy.simple.databinding.ActivityDbTestBinding;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DbTestActivity extends BaseActivity<ActivityDbTestBinding> {
|
||||
@Override
|
||||
protected int setLayoutId() {
|
||||
return R.layout.activity_db_test;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(Bundle savedInstanceState) {
|
||||
super.init(savedInstanceState);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.insert:
|
||||
insertManyRecord(10000);
|
||||
break;
|
||||
case R.id.search:
|
||||
break;
|
||||
case R.id.search_all:
|
||||
searchAll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void searchAll(){
|
||||
long startT = System.currentTimeMillis();
|
||||
//List<DownloadTaskEntity> data = DownloadEntity.findRelationData(DownloadEntity.class);
|
||||
|
||||
long endT = System.currentTimeMillis();
|
||||
Log.d(TAG, "search_time=" + (endT - startT));
|
||||
}
|
||||
|
||||
private void insertManyRecord(int len) {
|
||||
long startT = System.currentTimeMillis();
|
||||
List<DbEntity> datas = new ArrayList<>();
|
||||
for (int i = 0; i < len; i++) {
|
||||
String key = UUID.randomUUID().toString();
|
||||
String url = "https://blog.csdn.net/carefree31441/article/details/3998553";
|
||||
|
||||
DownloadEntity entity = new DownloadEntity();
|
||||
entity.setUrl(url);
|
||||
entity.setFileName("ssssssssssssssssss");
|
||||
entity.setDownloadPath(key);
|
||||
|
||||
DownloadTaskEntity dte = new DownloadTaskEntity();
|
||||
dte.setUrl(url);
|
||||
dte.setKey(key);
|
||||
dte.setEntity(entity);
|
||||
|
||||
datas.add(entity);
|
||||
datas.add(dte);
|
||||
}
|
||||
|
||||
//AbsEntity.insertManyData(DownloadEntity.class, datas);
|
||||
AbsEntity.saveAll(datas);
|
||||
long endT = System.currentTimeMillis();
|
||||
|
||||
Log.d(TAG, "insert_time=" + (endT - startT));
|
||||
}
|
||||
}
|
||||
33
app/src/main/res/layout/activity_db_test.xml
Normal file
33
app/src/main/res/layout/activity_db_test.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/layout_bar"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/insert"
|
||||
android:onClick="onClick"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="插入"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/search"
|
||||
android:onClick="onClick"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="查询"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/search_all"
|
||||
android:onClick="onClick"
|
||||
android:text="查询全部"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
Reference in New Issue
Block a user