【发布时间】:2018-06-17 20:42:53
【问题描述】:
在本地数据库中,我记录了有关目录和文件(文件系统树)的信息。例如,表“Dir”具有以下属性:record_id (autoincr.)、dir_id、dirname、parentDir_id。 我需要从数据库创建一个文件和目录树:
Dir_1
|
-----Dir_1.1
-----Dir_1.2
-----File_1.1
Dir_2
|
-----Dir_2.1
-----Dir_2.2
-----File_2.1
-----File_2.2
Dir_3
File_1
File_2
所以,我使用递归方法。 我的功能:
/**
* Append new childs for target dir
* @param targetObject directory
*/
public void addChilds(@Nullable SimpleSyncDirModel targetObject){
//no target - main parent dir.
if (targetObject == null){
//get childs for this target object (main dir without parent)
ArrayList<Object> foundedChilds = ThisApp.getDBhelper().getSharedSimpleObjects(this.dir_id);
//step by step (childs). recursive mecthod.
for (Object thisChild : foundedChilds){
if (thisChild instanceof SimpleSyncDirModel){
addNewChildDir((SimpleSyncDirModel) thisChild);
//find and add childs for current child
addChilds((SimpleSyncDirModel) thisChild);
}else if (thisChild instanceof SimpleSyncFileModel){
addNewChildFile((SimpleSyncFileModel) thisChild);
}
}
}else{
//get childs for this target object (not main, has parent)
ArrayList<Object> foundedChilds = ThisApp.getDBhelper().getSharedSimpleObjects(targetObject.dir_id);
//iterate, find and append childs (recursive)
for (Object thisChild : foundedChilds){
if (thisChild instanceof SimpleSyncDirModel){
targetObject.addNewChildDir((SimpleSyncDirModel) thisChild);
//recursive
addChilds((SimpleSyncDirModel) thisChild);
}else if (thisChild instanceof SimpleSyncFileModel){
targetObject.addNewChildFile((SimpleSyncFileModel) thisChild);
}
}
}
}
如你所见,我使用函数
ThisApp.getDBhelper().getSharedSimpleObjects(targetObject.dir_id);
用于搜索目标目录的子目录。 targetObject.dir_id - "SELECT" 的 parent_id。
我的搜索子功能:
/**
* Get childs with parent_id == 0 (without parent) or not (with parent)
* @param parendDir_id ID of dir, for what we search childs
* @return list of childs like {@link SimpleSyncDirModel}
* and {@link ru.rsit.megashare.models.global.SimpleSyncFileModel}
*/
public ArrayList<Object> getSharedSimpleObjects(String parendDir_id){
ArrayList<Object> result = new ArrayList<>();
//looking child dirs
String[] columns_ = new String[]{
"dir_id", "dirnameWithPath"
};
Cursor db_cursor = megashare_db.query(
"SharedDir", columns_,
"(parentDir_id = ?)",
new String[] { parendDir_id },
null, null, null);
if (db_cursor.getCount() > 0) {
db_cursor.moveToFirst();
while (db_cursor.getPosition() != db_cursor.getCount()) {
SimpleSyncDirModel simpleSyncDirModel = new SimpleSyncDirModel();
simpleSyncDirModel.dir_id =
Integer.toString(db_cursor.getInt(db_cursor.getColumnIndex("dir_id")));
simpleSyncDirModel.dirnameWithPath =
db_cursor.getString(db_cursor.getColumnIndex("dirnameWithPath"));
result.add(simpleSyncDirModel);
db_cursor.moveToNext();
}
}
db_cursor.close();
//looking child files
columns_ = new String[]{
"file_id", "filenameWithPath"
};
db_cursor = megashare_db.query(
"SharedFile", columns_,
"(parentDir_id = ?)",
new String[] { parendDir_id },
null, null, null);
if (db_cursor.getCount() > 0) {
db_cursor.moveToFirst();
while (db_cursor.getPosition() != db_cursor.getCount()) {
SimpleSyncFileModel simpleSyncFileModel = new SimpleSyncFileModel();
simpleSyncFileModel.file_id =
Integer.toString(db_cursor.getInt(db_cursor.getColumnIndex("file_id")));
simpleSyncFileModel.filenameWithPath =
db_cursor.getString(db_cursor.getColumnIndex("filenameWithPath"));
result.add(simpleSyncFileModel);
db_cursor.moveToNext();
}
}
db_cursor.close();
return result;
}
当我运行我的应用程序并尝试创建文件系统树时,我总是看到 java.lang.StackOverflowError:
FATAL EXCEPTION: Thread-23110
java.lang.StackOverflowError
at java.lang.ref.WeakReference.<init>(WeakReference.java:108)
at java.util.WeakHashMap$Entry.<init>(WeakHashMap.java:71)
at java.util.WeakHashMap.put(WeakHashMap.java:611)
at android.database.sqlite.SQLiteConnectionPool.finishAcquireConnectionLocked(SQLiteConnectionPool.java:980)
at android.database.sqlite.SQLiteConnectionPool.tryAcquirePrimaryConnectionLocked(SQLiteConnectionPool.java:916)
at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:682)
at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:400)
at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:905)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:586)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1436)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1283)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1154)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1322)
at ru.rsit.megashare.managers.DBHelper.getSharedSimpleObjects(DBHelper.java:582)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:64)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at ru.rsit.megashare.models.global.SimpleSyncDirModel.addChilds(SimpleSyncDirModel.java:70)
at
错误在这里:Cursor db_cursor = megashare_db.query
为什么会出现这个错误?当然我总是关闭光标。我需要做些什么来解决这个问题?
【问题讨论】:
-
在开发递归查询时,请始终使用
LIMIT 100或任何您能想象到的最多结果数来创建安全网。这样,如果您错过了一些递归结束的特殊情况,您仍然可以获得有价值的调试信息。 -
@Yunnosch,我明白了。但是我有两个主要目录,其中的孩子数量不超过 80 件。对不起我的英语。
-
这并不能保证 amok 递归保持少于 200 或 200000 个结果行。
-
我现在将尝试再次跟踪此代码。也许这个递归永远不会结束。但我不这么认为
-
我建议你通过调用
addChilds(this)来初始化递归,如果参数是null,addChilds不会做任何事情:if (targetObject == null) { return; } else { .... your code ... }。这样可以避免重复代码,如果getSharedSimpleObjects返回一个包含null的列表,也可以避免潜在的循环。
标签: java android sql sqlite recursion