Java 快速检查数据库中是否存在一组项

Java 快速检查数据库中是否存在一组项,java,hibernate,postgresql,Java,Hibernate,Postgresql,我有一个外部服务,我从中获取项目列表,并在本地保持这些项目与用户之间的关系。我为该外部服务提供了一个名称,并返回具有该名称的关联项。我之所以选择在本地持久化它们,是因为我希望在我的应用程序发现这些外部项后保留它们的属性。这些项目本身是相当静态的对象,但我不知道它们的总数,我唯一了解新项目的时间是新用户是否在外部服务上与它们有关联 当我从外部服务获得它们的列表时,我想首先检查它们是否存在于我的数据库中,并使用该对象,但如果不存在,我需要添加它们,以便设置自己的属性并保持与用户的关联 现在我有以下内

我有一个外部服务,我从中获取项目列表,并在本地保持这些项目与用户之间的关系。我为该外部服务提供了一个名称,并返回具有该名称的关联项。我之所以选择在本地持久化它们,是因为我希望在我的应用程序发现这些外部项后保留它们的属性。这些项目本身是相当静态的对象,但我不知道它们的总数,我唯一了解新项目的时间是新用户是否在外部服务上与它们有关联

当我从外部服务获得它们的列表时,我想首先检查它们是否存在于我的数据库中,并使用该对象,但如果不存在,我需要添加它们,以便设置自己的属性并保持与用户的关联

现在我有以下内容(伪代码,因为它被分解为服务层等):

Set items=externalService.getItemsForUser(user.name);
对于(外部项外部项:项){
Item dbItem=sessionFactory.getCurrentSession().get(Item.class,Item.id);
if(dbitem==null){
//不在数据库中,创建它。
dbItem=mapToItem(外部项);
} 
user.addItem(数据库项);
}
sessionFactory.getCurrentSession().save(用户)//还保存关联的项目。
对于大约500个外部项目,此操作所需的时间约为16秒。远程操作大约为1秒,节省的时间也可以忽略不计。我注意到的消耗来自我正在进行的大量
会话.get(Item.class,Item.id)
调用

考虑到我从外部服务中得到了一个回退,有没有比这更好的方法来检查数据库中的现有项


注意:外部项的id与我的id相同是可靠的,并且单个id始终表示相同的外部项

我肯定会推荐本机查询,如注释中所建议的那样

不过,考虑到你所说的数字,我不想费心把它们切碎。Postgres应该能够处理一个包含500个元素的
IN
子句,没有问题。我已经通过编程生成了查询,其中包含的项目比执行良好的查询多得多


通过这种方式,您也只有一次往返,假设有适当的索引,这应该在亚秒的时间内完成。

如果您不想添加另一个数据结构(过滤器),我能想象的唯一一件事是减少到数据库的往返(并确保itemID上有索引)。使用带有IN(id1,id2,id3)构造的本机SQL查询可以减少往返。不幸的是,我认为这需要通过构造具有多个参数的大小相等的准备语句来手动完成。(保持变量的数量较小)。@eckes所以我想我会将它们分成20个左右的组,执行本机选择id所在的位置(id1,id2,…,id20),然后研究返回的结构,以返回原始列表中的哪些id。是的,因此110个结果将是15个往返(5 x 20+10 x 1),只有2个不同的语句需要解析。或者,根据通常检查的项目数量范围,您可以选择100、10和1。我不确定Hibernate是否为此提供了帮助。顺便说一句:如果不请求
对象(或者只是懒洋洋地加载它),您也可以在ORM层上保存处理,因此SQL语句将只返回ItemID(string)列,而不是所有列。(或者,如果不批处理,则只返回计数)。我这样做,迭代外部id,将它们添加到集合中,然后从id位于(…)的项目中查询
select*,并返回匹配的id列表。然后,我再次迭代了原始的外部项集,对于结果集中的每一项,我都执行了
session.load()
,对于结果集中不存在的每一项,我都创建了新项,并随后保存了所有内容。这个操作现在有2-3秒长,这对于一个webapp来说更为合理。
Set<ExternalItem> items = externalService.getItemsForUser(user.name);
for (ExternalItem externalItem : items){
    Item dbItem = sessionFactory.getCurrentSession().get(Item.class,item.id);
    if (dbitem == null){
        //Not in database, create it.
        dbItem = mapToItem(externalItem);
    } 
    user.addItem(dbItem);

}
sessionFactory.getCurrentSession().save(user);//Saves the associated Items also.