我通过可滚动的结果集从hibernate中获取大表(约100万个条目)中的数据。我现在面临的问题非常奇怪,现在我似乎找不到答案。
我所做的是使用非常简单的语句加载数据,滚动结果集并将XML字符串写入zip文件。我正在批处理查询,因为Hibernate在" WHERE IN - 子句"中的参数数量有问题。达到一定数量。将其设置为常规ParameterList更糟糕。这就是我为什么这样做的方式。
现在问题:我正在从SQL(业务键+类型)中定义的唯一键生成文件名。在这个过程中,我得到一个zipException,它说文件名已经存在。这应该是不可能的,因为唯一键可以防止重复输入。是否有可能我以某种方式错误地使用了scrollable结果?是否需要批量获取数据导致此问题?我真的在这里无能为力......
CREATE TABLE "lmh_repository"
(
ID_REPOSITORY decimal(19,0) PRIMARY KEY IDENTITY (1,1) NOT NULL,
ENTITY_TYPE varchar(255) NOT NULL,
ENTITY_ID varchar(255) NOT NULL,
ENTITY_VERSION int DEFAULT ((0)) NOT NULL,
XML_DATA varbinary(MAX) NOT NULL
);
ALTER TABLE "lmh_repository"
ADD CONSTRAINT UQ_ENTITY_TYPE_ID UNIQUE(ENTITY_TYPE, ENTITY_ID)
现在提取数据的代码。
private void fetchXMLDataFromDB(Set<String> idList, ArchiveOutputStream aos, EntityTypeEnum type) {
// not more than 5000 to avoid hibernate issues in 'WHERE IN - clause'
Iterable<List<String>> partition = Iterables.partition(idList, BATCH_SIZE);
StatelessSession session = sessionFactory.openStatelessSession();
try {
for (List<String> listPartition : partition) {
String ids = getWhereInClause(listPartition);
ScrollableResults scrollableResults = session.createQuery("FROM " + LMHRepository.class.getSimpleName() +
" WHERE entityType = :type AND entityId IN (" + ids + ")")
.setParameter("type", type)
.scroll(ScrollMode.FORWARD_ONLY);
while (scrollableResults.next()) {
LMHRepository repoFile = (LMHRepository) scrollableResults.get()[0];
String fileName = getFileName(repoFile);
aos.putArchiveEntry(new ZipArchiveEntry(fileName));
IOUtils.write(repoFile.getXmlStringData(), aos);
aos.closeArchiveEntry();
}
}
} catch (IOException e) {
//error handling
} finally {
session.close();
}