Java 数据库中的NotesDocument对象和内存中的NotesDocument对象之间的区别?

Java 数据库中的NotesDocument对象和内存中的NotesDocument对象之间的区别?,java,lotus-domino,Java,Lotus Domino,我在我的一个Java代理中注意到,当在Hashmap中存储大量文档对象时,我得到了OutofMemoryException。 我试图实现的是: 我想用Oracle数据库中的信息填充Domino数据库。逻辑是从Oracle获取所有文档,然后从Domino数据库获取所有文档。所有来自Oracle的新内容都将被保存,所有不在Oracle中但在数据库中的内容都将从Domino中删除。你的某种复制品将 我首先循环Domino数据库中的所有文档,并将它们存储在一个HashMap中,UNID作为键,Docum

我在我的一个Java代理中注意到,当在Hashmap中存储大量文档对象时,我得到了OutofMemoryException。 我试图实现的是:

我想用Oracle数据库中的信息填充Domino数据库。逻辑是从Oracle获取所有文档,然后从Domino数据库获取所有文档。所有来自Oracle的新内容都将被保存,所有不在Oracle中但在数据库中的内容都将从Domino中删除。你的某种复制品将

我首先循环Domino数据库中的所有文档,并将它们存储在一个HashMap中,UNID作为键,Document object作为值:

dominoHash.put(doc.getUniversalId(), doc);
然后我循环结果集并创建内存中的文档对象:

Document doc = db.createDocument();
doc.replaceItemValue("MyField", rset.getString("MYCOLUMN");
oracleHash.put(rset.getString("UNID"), doc);
在我的测试环境中,我有+20000个Domino文档,在Oracle中也是如此。在这种情况下,它们是相同的。 在尝试存储到oracleHash中时,总是会发生OutOfMemoryException,即使我已从代码中排除了所有Domino文档逻辑以“保存内存”

我认为我存储在不同HashMap中的对象是相同的,但有些是不同的。我可以成功地将Domino文档对象存储在Hashmap中,但不能存储Oracle文档对象

更奇怪的是,从Domino存储的文档的字段比Oracle视图的列多

为什么可能是原因呢


在这个特定的例子中,我使用org.openntf.dominoapi,但还没有尝试过原生API。

将所有domino文档保存在内存中并不是一个好主意。在某个时间点,您会用完核心API中的C句柄

你可能想要/需要改变你的方法。一旦达到“大小”,试图将所有内容都保留在内存中,内存就会耗尽。你需要的是,用@Andre Guirard恰当地命名为“海盗算法”:

在Domino和Oracle中各有一个视图,它们是按比较键排序的。假设N是Notes,O是Oracle。您的代码(此处为伪代码)大致如下所示:

         OEntry = O.getFirst
         for all NEntry in N
             if NEntry.key > OEntry.key
                InsertFromOracle until NEntry.key = OEntry.key
             else if Nentry.key < OEntry.key
                DeleteFromNotes until NEntry.key = OEntry.key
             else
                SyncValuesFromOracleToNotes
             end if
          end for
         if O.hasMoreEntries
             InsertFromOracle until not O.hasMoreEntries
         end if
OEntry=O.getFirst
对于N中的所有Entry
如果entry.key>OEntry.key
从Oracle插入到entry.key=OEntry.key
否则,如果entry.key
InsertFromOracle当然需要检查Oracle中是否还有元素可以执行此操作

一本由安德烈写的书(寻找海盗特工,以海盗的昂首阔步命名)

您不需要将整个表或文档集合保存在内存中。由于加载和比较在单个循环中运行,因此它也应该表现得相当好


让我们知道进展如何

如果这是一个XAgent,当多个会话命中或运行多个请求时,您会遇到内存异常,那么很可能这与持久性有关。页面的许多会话/实例可能被保存在内存中,导致每次都将其添加到页面的上一次调用的内存中,这就是导致最终OutOfMemoryException的原因

如果它是XPage上运行该进程的唯一内容,请将viewState属性设置为“nostate”。如果这就是数据库正在做的所有事情,那么可以在Xsp属性中设置它


或者,如果您需要序列化和检索XPages本身中的数据,那么在Xsp属性的persistence选项卡上将“Server page persistence”设置为“Keep page on disk”应该可以解决这个问题。没有任何东西会被存储在内存中。加载页面后,其数据将存储在磁盘上。

我可以确认,这是Java OutOfMemory异常还是由于查找句柄而导致死机?显然,R9的Domino句柄限制是150000,所以它不应该达到这个限制。但是,由于您将文档放入地图中,API无法回收它们,因为它们仍在使用中。您可以使用lotus.domino.Document和lotus.domino.Database显式地使用非ODA对象。但有趣的是,当我从oracle而不是domino创建内存中的对象时,我得到了它。异常的堆栈后跟踪。如果这是纯java代理,那么它不是XPages,您应该删除XPages标记。如果是“XAgent”,那么显然你应该保留标签。我不确定是哪一个,所以你应该说清楚。Thanks@PaulStephenWithers我开始倾向于您的答案,即所有Domino对象都没有被回收。今天早上我成功地循环并添加到Maps所有资源,没有任何MemoryException,我想如果我今天多次运行代理,内存将满…唯一的解决方案是循环所有SQL对象和所有Domino对象,但这将创建巨大的I/O…我的意图是创建映射并使用集合方法来删除和保留。JDBC连接似乎比我预期的对内存的影响更大。我会尝试“海盗”的方法。Thxy你可能真的想探索DEC或LEI。可能比自己编写代码更聪明。我在这里写道:我已将其更改为不在内存中存储任何文档,但仍面临OutOfMemoryException:
11-11-2014 14:44:34 AMgr:Agent('R7\tradesec.nsf'中的导入债券副本| aImportBonds2'))错误消息:11-11-2014 14:44:34 se.tradechannel.agents.ImportBondsImpl NotesMain INFO:start Copy Of Import Bonds 11-11-2014 14:45:25 AMgr:Agent(“R7\tradesec.nsf中的导入债券副本| aImportBonds2”)错误消息:JVMDUMP039I正在处理转储事件“systhrow”,详细信息“java/lang/OutOfMemoryError”2014/11/11 14:45:25-请稍候。
有了64MB的堆,你哪儿也去不了。这两个数据都不能使用HashMap