我的桌子看起来像这样;
@Table
public class Person {
private String name;
private String address;
...
private String score;
}
在我的数据库中,我现在有很多名字,地址和分数的人。假设我从另一个系统中检索一个人员列表,其中一些人已经存在于数据库中,一些人是新的。
在我将它们保存在我的数据库中之前,我想检查它们是否已经存在(避免重复),如果我进入的人与我已经拥有的人相同但是得分不同,则可能会改变分数。
如果我想选择所有存在的人,那么最好的查询是什么? (例如,相同的名称和地址)。我的人员表可能包含大量人员,而我从其他系统进入的人员名单也很大(新的或更新的分数)。我需要一个关于性能的查询:-)。
我正在使用Java和Hibernate。任何人吗?
编辑:最终的sql可能看起来像
select * from Person where name='Paul' AND address='road1
OR name='John' AND address='road2'
OR name='Stella' AND address='road3'
以及更多......上面的sql atleast解释了我想要的东西。
答案 0 :(得分:0)
这样做的一种方法是外连接两个表并列出一侧不存在的所有人。像这样(TSQL):
SELECT left.* from db1.owner.persons left LEFT JOIN db2.owner.persons right ON left.name=right.name AND left.address=right.address WHERE right.id IS NULL
然后,您可以使用ISession的CreateSQLQuery方法获取人员列表。
在C#中我们这样写
var list=session.CreateSQLQuery(queryString,"left",new []{typeof(Person)}).List();
但我不认为这与java有很大不同
如果你想获得这个查询的性能,可能需要在每个表上放一些索引(例如,通过名称和地址)
答案 1 :(得分:0)
如果我理解正确,你已经拥有了所有“外部”人。
我会创建一个Map<String, ExternalPerson>
,其中包含按名称索引的所有外部人员。
然后我会要求此地图的keySet()
获取从数据库中获取的人员列表。
然后我会执行以下查询:
select p from Person p where p.name in (:names)
您只需确保名称数量不超过数据库强加的限制(Oracle中为1000)。如果是这样,您必须将该集合拆分为多个子集,并对每个子集重复查询。
然后迭代查询结果。对于找到的每个人,使用地图或外部人员获取其相应的外部人员,并更新当前人员的分数。然后从地图中删除外部人员。
在流程结束时,地图包含数据库中不存在的外部人员,并且必须创建。
如果这组人真的很高兴,请确保使用query.scroll()
而不是query.list()
来迭代这些人,并定期刷新并清除会话,如this section of the reference manual中所述,避免记忆问题。