Kic*_*obo 6 java ms-access jdbc jdbc-odbc
在工作中我们必须处理几个MS Access mdb文件,因此我们使用Sun JVM附带的默认JdbcOdbcBridge驱动程序,并且在大多数情况下,它运行良好.
问题是,当我们必须处理一些较大的文件时,我们会遇到几次异常,并显示"无法打开更多表"的消息.我们怎么能避免这种情况?
我们已经关闭了PreparedStatements和RecordSet的所有实例,甚至将它们的变量设置为null,但即便如此,这种异常仍会继续发生.我们应该做什么?我们怎样才能避免这些讨厌的例外?这里有人知道怎么样?
是否有任何其他配置到Windows上的ODBC驱动程序,我们可以更改以避免此问题?
Dav*_*ton 10
"无法再打开表"是一个比"无法打开更多数据库"更好的错误消息,这在我的经验中更常见.事实上,后一种消息几乎总是掩盖前者.
Jet 4数据库引擎限制为2048个表句柄.我不完全清楚这是在连接的生命周期中是同时还是累积的.我一直认为它是累积性的,因为在实践中一次打开更少的记录集似乎可以避免这个问题.
问题是"表句柄"不只是引用表句柄,而是引用更多内容.
考虑使用此SQL保存的QueryDef:
SELECT tblInventory.* From tblInventory;
Run Code Online (Sandbox Code Playgroud)
运行QueryDef使用两个表句柄.
什么?,你可能会问?它只使用一张桌子!但Jet使用表的句柄和保存的QueryDef的表句柄.
因此,如果您有这样的QueryDef:
SELECT qryInventory.InventoryID, qryAuthor.AuthorName
FROM qryInventory JOIN qryAuthor ON qryInventory.AuthorID = qryAuthor.AuthorID
Run Code Online (Sandbox Code Playgroud)
...如果每个源查询中都有两个表,则使用这些表句柄,每个句柄一个:
Table 1 in qryInventory
Table 2 in qryInventory
qryInventory
Table 1 in qryAuthor
Table 2 in qryAuthor
qryAuthor
the top-level QueryDef
Run Code Online (Sandbox Code Playgroud)
因此,您可能认为只涉及四个表(因为只有四个基表),但实际上您将使用7个表句柄来使用这4个基表.
如果在记录集中,然后使用保存的QueryDef使用7个表句柄,那么你已经用完了另一个表句柄,总共8个.
回到Jet 3.5天,原来的表处理限制是1024,当我在设计一个有效的应用程序后复制数据文件时,我在截止日期遇到了它.问题是一些复制表是一直打开的(可能是每个记录集?),并且用尽了足够多的表句柄将应用程序放在顶部.
在该应用程序的原始设计中,我打开了一堆包含大量子表单和组合框以及列表框的重量级表单,当时我使用了大量已保存的QueryDef来预先组装我在很多地方使用的标准记录集(就像你在任何服务器数据库上查看一样).解决问题的原因是:
仅在显示子表单时加载子表单.
只有当它们在屏幕上时才加载组合框和列表框的行源.
尽可能删除所有已保存的QueryDef并使用加入原始表的SQL语句.
这使我能够在伦敦办公室部署该应用程序仅比计划晚一周.当Jet SP2出现时,它将表句数量增加了一倍,这就是我们在Jet 4中所拥有的(我认为是ACE).
关于通过ODBC从Java使用Jet,关键点是,我认为:
在整个应用程序中使用单个连接,而不是根据需要打开和关闭它们(这会使您无法关闭它们).
只在您需要时打开记录集,并在完成后清理并释放其资源.
现在,可能是在JDBC => ODBC => Jet链中的某处存在内存泄漏,您认为您正在释放资源并且它们根本没有被释放.我没有任何特定于JDBC的建议(因为我没有使用它 - 毕竟我是Access程序员),但是在VBA中我们必须小心显式关闭我们的对象并释放它们的内存结构,因为VBA使用引用计数,有时它不知道对象的引用已被释放,因此当它超出范围时,它不释放该对象的内存.
所以,在VBA代码中,每次执行此操作时:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = DBEngine(0).OpenDatabase("[database path/name]")
Set rs = db.OpenRecordset("[SQL String]")
Run Code Online (Sandbox Code Playgroud)
...在你完成了你需要做的事之后,你必须完成这个:
rs.Close ' closes the recordset
Set rs = Nothing ' clears the pointer to the memory formerly used by it
db.Close
Set db = Nothing
Run Code Online (Sandbox Code Playgroud)
...即使你声明的变量在该代码之后立即超出范围(这应该释放它们使用的所有内存,但不能100%可靠地执行).
现在,我不是说这是你用Java做的,但我只是建议如果你遇到问题并且你认为你正在释放所有资源,那么你可能需要确定你是否依赖于垃圾收集这样做,而是需要明确地这样做.
请原谅我,如果我说过任何关于Java和JDBC的愚蠢行为 - 我只是报告了Access开发人员与Jet交互的一些问题(通过DAO,而不是ODBC)报告相同的错误消息您将获得,希望我们的经验和实践可以为您的特定编程环境提供解决方案.
归档时间: |
|
查看次数: |
8453 次 |
最近记录: |