优化数据库写入\修改的速度

v3.6.6
laoyuyu 6 years ago
parent e3a27ab7a2
commit 40c210c751
  1. 18
      Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java
  2. 63
      Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java
  3. 110
      Aria/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java
  4. 21
      Aria/src/main/java/com/arialyy/aria/orm/DelegateWrapper.java
  5. 4
      DEV_LOG.md
  6. 2
      app/src/main/AndroidManifest.xml
  7. 76
      app/src/main/java/com/arialyy/simple/DbTestActivity.java
  8. 33
      app/src/main/res/layout/activity_db_test.xml

@ -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} 存在
*/
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,41 +101,75 @@ 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();
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 {
for (Field field : fields) {
field.setAccessible(true);
if (isIgnore(dbEntity, field)) {
continue;
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);
}
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);
ContentValues value = createValues(entity);
if (value == null) {
ALog.e(TAG, "更新记录失败,记录没有属性字段");
} else {
Object obj = field.get(dbEntity);
value = obj == null ? "" : obj.toString();
db.update(table, value, "rowid=?", new String[] {String.valueOf(entity.rowID)});
}
values.put(field.getName(), encodeStr(value));
}
} catch (IllegalAccessException e) {
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
if (values.size() > 0) {
db.update(CommonUtil.getClassName(dbEntity), values, "rowid=?",
new String[] { String.valueOf(dbEntity.rowID) });
}
/**
* 插入多条记录
*/
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 {
ALog.d(TAG, "没有数据更新");
entity.rowID = db.insert(table, null, value);
}
}
close(db);
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
/**
@ -143,8 +177,22 @@ class DelegateUpdate extends AbsDelegate {
*/
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"/>

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

@ -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>
Loading…
Cancel
Save