greendao -android.database.cursorwindowallocationexception:无法分配Cursorwindow< dbname>由于错误-12,大小104857600

发布于 2025-02-13 13:26:32 字数 4437 浏览 0 评论 0 原文

因此,我基本上是在 greendao 生成的表中分析JSON并存储了〜3000行(无多媒体),并且在此功能中查询数据时会从上述错误中遇到上述错误:

    @Synchronized
    private fun checkGroupVisibility(
        dependencyList: ArrayList<Long>,
        dependencyType: String,
        mInspectionId: Long,
        isFromPhilosophyFlow: Boolean,
        daoSession: DaoSession?,
        string: String?
    ): Boolean {
        var show = true
//        Log.d("TAG", "checkGroupVisibility: lock testing 2"+string)
        if (!DataSanityUtils.isListEmpty(dependencyList)) {
            //check further in database if dependency question is answered
            val inspectionReportCarParList:List<InspectionReportCarPart>? = daoSession?.inspectionReportCarPartDao?.queryBuilder()
                ?.where(InspectionReportCarPartDao.Properties.InspectionID.eq(mInspectionId))
                ?.where(InspectionReportCarPartDao.Properties.QuestionId.`in`(dependencyList))
                ?.list()

            val inspectionReportCheckpointList:List<InspectionReportCheckpoint>? = daoSession?.inspectionReportCheckpointDao?.queryBuilder()
                ?.where(InspectionReportCheckpointDao.Properties.InspectionID.eq(mInspectionId))
                ?.where(InspectionReportCheckpointDao.Properties.ReportCheckpointVerdict.eq(CommonConstants.CHECKPOINT_VERDICT_NOT_OKAY))
                ?.list()

            for (checkPointId in dependencyList) {
                if (!isFromPhilosophyFlow && philosophyIdCheckPointMap.containsKey(checkPointId)) {
                    show = false
                    break
                }
                val isCarPartFound:InspectionReportCarPart?= inspectionReportCarParList?.find {
                    it.questionId==checkPointId
                }

                if (isCarPartFound==null) {
                    val isFound= inspectionReportCheckpointList?.find {
                        it.optionId==checkPointId
                    }
                    if (isFound == null) {
                        show = false
                        if (CommonConstants.DEPENDENCY_RELATION_AND.equals(
                                dependencyType,
                                ignoreCase = true
                            )
                        ) {
                            break
                        }
                    } else if (CommonConstants.DEPENDENCY_RELATION_OR.equals(
                            dependencyType,
                            ignoreCase = true
                        )
                    ) {
                        show = true
                        break
                    }
                } else if (CommonConstants.DEPENDENCY_RELATION_OR.equals(
                        dependencyType,
                        ignoreCase = true
                    )
                ) {
                    show = true
                    break
                }
            }
        }
//        Log.d("TAG", "checkGroupVisibility: lock testing 3:"+string)
        return show
    }

当评估<<时,确切的错误正在出现。代码>检查ReportCarparlist (即代码中的第一个查询)。这是完整的stacktrace:

android.database.CursorWindowAllocationException: Could not allocate CursorWindow '/data/user/0/com.example.visor/databases/report.json-db' of size 104857600 due to error -12.
    at android.database.CursorWindow.nativeCreate(CursorWindow.java)
    at android.database.CursorWindow.<init>(CursorWindow.java:139)
    at android.database.CursorWindow.<init>(CursorWindow.java:120)
    at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:202)
    at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:149)
    at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:142)
    at de.greenrobot.dao.AbstractDao.loadAllFromCursor(AbstractDao.java:371)
    at de.greenrobot.dao.AbstractDao.loadAllAndCloseCursor(AbstractDao.java:184)
    at de.greenrobot.dao.InternalQueryDaoAccess.loadAllAndCloseCursor(InternalQueryDaoAccess.java:21)
    at de.greenrobot.dao.query.Query.list(Query.java:130)
    at de.greenrobot.dao.query.QueryBuilder.list(QueryBuilder.java:353)
    at com.example.inspectionreport.utils.ReportUtils.checkGroupVisibility(ReportUtils.kt:31)

我也使用 de.greenrobot:greendao:2.0.0 此版本的Greendao。

我认为Greendao应该处理所有Cusrsor动作,并且在查询自己后关闭了光标。但是,Cursorwindow的尺寸仍然越来越大,应用程序崩溃了。请帮忙!

So I basically parse a JSON and store ~3000 rows (no multimedia) in the greendao generated table and I am getting the above error from while querying data in this function:

    @Synchronized
    private fun checkGroupVisibility(
        dependencyList: ArrayList<Long>,
        dependencyType: String,
        mInspectionId: Long,
        isFromPhilosophyFlow: Boolean,
        daoSession: DaoSession?,
        string: String?
    ): Boolean {
        var show = true
//        Log.d("TAG", "checkGroupVisibility: lock testing 2"+string)
        if (!DataSanityUtils.isListEmpty(dependencyList)) {
            //check further in database if dependency question is answered
            val inspectionReportCarParList:List<InspectionReportCarPart>? = daoSession?.inspectionReportCarPartDao?.queryBuilder()
                ?.where(InspectionReportCarPartDao.Properties.InspectionID.eq(mInspectionId))
                ?.where(InspectionReportCarPartDao.Properties.QuestionId.`in`(dependencyList))
                ?.list()

            val inspectionReportCheckpointList:List<InspectionReportCheckpoint>? = daoSession?.inspectionReportCheckpointDao?.queryBuilder()
                ?.where(InspectionReportCheckpointDao.Properties.InspectionID.eq(mInspectionId))
                ?.where(InspectionReportCheckpointDao.Properties.ReportCheckpointVerdict.eq(CommonConstants.CHECKPOINT_VERDICT_NOT_OKAY))
                ?.list()

            for (checkPointId in dependencyList) {
                if (!isFromPhilosophyFlow && philosophyIdCheckPointMap.containsKey(checkPointId)) {
                    show = false
                    break
                }
                val isCarPartFound:InspectionReportCarPart?= inspectionReportCarParList?.find {
                    it.questionId==checkPointId
                }

                if (isCarPartFound==null) {
                    val isFound= inspectionReportCheckpointList?.find {
                        it.optionId==checkPointId
                    }
                    if (isFound == null) {
                        show = false
                        if (CommonConstants.DEPENDENCY_RELATION_AND.equals(
                                dependencyType,
                                ignoreCase = true
                            )
                        ) {
                            break
                        }
                    } else if (CommonConstants.DEPENDENCY_RELATION_OR.equals(
                            dependencyType,
                            ignoreCase = true
                        )
                    ) {
                        show = true
                        break
                    }
                } else if (CommonConstants.DEPENDENCY_RELATION_OR.equals(
                        dependencyType,
                        ignoreCase = true
                    )
                ) {
                    show = true
                    break
                }
            }
        }
//        Log.d("TAG", "checkGroupVisibility: lock testing 3:"+string)
        return show
    }

The exact error is coming when evaluating inspectionReportCarParList (i.e. the first query in the code). Here is the full stacktrace :

android.database.CursorWindowAllocationException: Could not allocate CursorWindow '/data/user/0/com.example.visor/databases/report.json-db' of size 104857600 due to error -12.
    at android.database.CursorWindow.nativeCreate(CursorWindow.java)
    at android.database.CursorWindow.<init>(CursorWindow.java:139)
    at android.database.CursorWindow.<init>(CursorWindow.java:120)
    at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:202)
    at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:149)
    at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:142)
    at de.greenrobot.dao.AbstractDao.loadAllFromCursor(AbstractDao.java:371)
    at de.greenrobot.dao.AbstractDao.loadAllAndCloseCursor(AbstractDao.java:184)
    at de.greenrobot.dao.InternalQueryDaoAccess.loadAllAndCloseCursor(InternalQueryDaoAccess.java:21)
    at de.greenrobot.dao.query.Query.list(Query.java:130)
    at de.greenrobot.dao.query.QueryBuilder.list(QueryBuilder.java:353)
    at com.example.inspectionreport.utils.ReportUtils.checkGroupVisibility(ReportUtils.kt:31)

Also I am using de.greenrobot:greendao:2.0.0 this version of greendao.

I thought greendao is supposed to handle all the cusrsor actions and it closes the cursor after querying itself. But still cursorWindow size is getting very huge and the application crashes. Please help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Bonjour°[大白 2025-02-20 13:26:32

光标窗口的大小有限(取决于Android版本,但最大为4MB)。 104857600是100MB,所以太大了。

Cursorwindow必须能够容纳1行或更多行,如果它不能容纳1行,那么您将会遇到这样的错误。

可以存储太大而无法检索的数据(这是图像的常见问题)。

处理如此大量数据的推荐方法是将数据(例如图像)存储在文件中,并将路径的路径或部分存储在数据库中。


其他评论

我明白了,但是在这种情况下,我不直接存储任何多媒体

此问题不仅限于多媒体,这只是数据太大的一个例子。它可以是字符串(文本)数据。

这是一个显示此情况的示例(仅使用sqlite,greendao基本上只是一个包装器),该示例还包括一个替代方案的示例,该替代方案没有经历该问题,因为它将报告的可管理部分存储在单独的详细信息中相关表。

考虑以下代码: -

public class MainActivity extends AppCompatActivity {

    DBHelper mDBHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDBHelper = DBHelper.getInstance(this);
        /* Generate the base string i.e. 1000K */
        String current_report_detail = generateReportDetail(1000);

        /* Insert Rows with 1000K report detail */
        mDBHelper.insertReportV1(System.currentTimeMillis() / 1000,current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail);

        /* Insert Rows with 2000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail);

        /* Insert Rows with 3000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail + current_report_detail);

        /* Insert Rows with 4000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail + current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail + current_report_detail + current_report_detail);

        /* Insert Rows with 5000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail + current_report_detail + current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail + current_report_detail + current_report_detail + current_report_detail);

    }

    /* return a String whose length is the passed linecount * 1024 i.e. 1K per line */
    private String generateReportDetail(int linecount) {
        StringBuilder sb1 = new StringBuilder();
        /* Build base line  of 1K of characters */
        for(int i=0; i < 1024; i++) {
            sb1.append((char) ((i % 95) + 33));
        }
        StringBuilder sb2 = new StringBuilder();
        for (int i=0;i<linecount;i++) {
            sb2.append(sb1.toString());
        }
        return sb2.toString();
    }
}

因此,有5个阶段每个阶段逐渐插入接近1MB的文本数据,沿着: -

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi

....

每个阶段插入相同的数据(1MB,2MB .... 5MB)两次。

  • 第一个将细节(字符串)的单个表格分为单个表。
  • 第二个表格分为两个表,主表保存静态报告数据(在这种情况下为日期)和一个表格的片段数据(分为1K块) IE 的解决方案 ie *。

运行时,使用应用程序检查,然后: -

  • 架构看起来像 “在此处输入图像说明”
    • v1是将有问题的单个表版本。
    • v2是规避与完全相同的核心数据的CursorWindow尺寸问题的示例
    • v2_details表包含冗长报告的块/部分(此示例中的1024个字节)

尝试读取V1_report表中的所有数据

如果 .sstatic.net/MH98b.png" rel="nofollow noreferrer">“在此处输入映像说明”

现在,对于v2_report,没有问题: -

“在此处输入图像说明”

作为长文本数据已被拆分并放置在v2_details表中: -

“在此处输入图像描述”

  • 左数是通过应用程序检查生成的行计数,显示15000行存在于细节。那就是细节已分为部分/块。

可以清楚地看到这个问题(还可以证明数据存在并已成功地插入v1_report): -

”

尽管不准确(该示例已迅速组合在一起,看来我丢弃了一个字节/字符) 可以从两个V2中提取等效词表按: -

“在此处输入映像”

  • so SO 而不是1024000,截面数据为1023000(即掉落1000个字节(即掉落1000个字节)排)。

A Cursor Window has a restricted size (depends upon the Android Version but up to 4Mb). 104857600 is 100Mb, so way too large.

A CursorWindow has to be able to accommodate 1 or more rows, if it cannot hold 1 row then you will get such an error.

It is possible to store data that is too large to be retrieved (it is a common issue with images).

The recommended way of handling such large amounts of data is to store the data, such as an image, in a file and store the path or part of the path in the database.


Additional re the comment

I got it but in this case I do not store any multimedia directly here

The issue is not limited to multimedia, that is just an example of the data being too large. It could be String (TEXT) data.

Here's an example that shows the case (just using SQLite which greenDao is basically just a wrapper around), the example also includes an example of an alternative that does not experience the issue as it stores managable sections of the details of the report in a separate related table.

Consider the following code:-

public class MainActivity extends AppCompatActivity {

    DBHelper mDBHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDBHelper = DBHelper.getInstance(this);
        /* Generate the base string i.e. 1000K */
        String current_report_detail = generateReportDetail(1000);

        /* Insert Rows with 1000K report detail */
        mDBHelper.insertReportV1(System.currentTimeMillis() / 1000,current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail);

        /* Insert Rows with 2000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail);

        /* Insert Rows with 3000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail + current_report_detail);

        /* Insert Rows with 4000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail + current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail + current_report_detail + current_report_detail);

        /* Insert Rows with 5000K eport detail */
        mDBHelper.insertReportV1(System.currentTimeMillis()/1000,current_report_detail + current_report_detail + current_report_detail + current_report_detail + current_report_detail);
        mDBHelper.insertReportV2(System.currentTimeMillis() / 1000, current_report_detail + current_report_detail + current_report_detail + current_report_detail + current_report_detail);

    }

    /* return a String whose length is the passed linecount * 1024 i.e. 1K per line */
    private String generateReportDetail(int linecount) {
        StringBuilder sb1 = new StringBuilder();
        /* Build base line  of 1K of characters */
        for(int i=0; i < 1024; i++) {
            sb1.append((char) ((i % 95) + 33));
        }
        StringBuilder sb2 = new StringBuilder();
        for (int i=0;i<linecount;i++) {
            sb2.append(sb1.toString());
        }
        return sb2.toString();
    }
}

So there are 5 stages each progressively inserting close to 1Mb of textual data along the lines of :-

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi

....

Each stage inserts the same data (1Mb,2Mb .... 5Mb) twice.

  • The first into a single table with the detail (the String).
  • The second into two tables, the main table to hold the static report data (date in this case) and a table to hold sections of the String data (split into 1k chunks) i.e. a solution to the issue*.

When run, using App Inspection, then:-

  • The schema looks like enter image description here
    • V1 is the single table version that will have issues.
    • V2 is an example of circumventing the CursorWindow size issues for EXACTLY THE SAME CORE DATA.
    • the v2_details table holds chunks/sections of the lengthy report (1024 bytes in this example)

If an attempt is made to read all of the data in the v1_report table then the CursorWindow size occurs:-

enter image description here

Now for v2_report, there is no issue :-

enter image description here

As the long textual data has been split and placed into the v2_details table :-

enter image description here

  • The left most number is the row count as generated by App Inspection, showing 15000 rows exist in the detail. That is the details has been split into sections/chunks.

The issue can be clearly seeing (also proving that the data exists and has been inserted successfully into v1_report) by using the following:-

enter image description here

Although not accurate (the example has been quickly put together and it looks as though I've dropped a byte/character) the equivalent can be extracted from both the v2 tables as per:-

enter image description here

  • so instead of 1024000, the sectioned data is 1023000 (i.e. 1000 bytes dropped which is 1 byte per row).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文