获取Java数据库中不存在的对象列表的有效方法
假设我有一个对象列表ArrayList对象和一个对象的db表,我想查找尚未存储在my数据库中的对象。对象由其id标识。我可以想出两种解决方案,但我不知道哪一种更有效 我想到的第一个解决方案是构造一个db查询,以获取db中存在的所有对象,并循环遍历现有对象以确定不在db中的对象获取Java数据库中不存在的对象列表的有效方法,java,sql,Java,Sql,假设我有一个对象列表ArrayList对象和一个对象的db表,我想查找尚未存储在my数据库中的对象。对象由其id标识。我可以想出两种解决方案,但我不知道哪一种更有效 我想到的第一个解决方案是构造一个db查询,以获取db中存在的所有对象,并循环遍历现有对象以确定不在db中的对象 ArrayList<Integer> ids = new ArrayList<Integer>(); for(MyObject o in objects){ ids.add(o.getId
ArrayList<Integer> ids = new ArrayList<Integer>();
for(MyObject o in objects){
ids.add(o.getId());
}
//I use sugar orm on Android, raw query can be seen as
// "select * from my_object where id in [ id1,id2,id3 ..... ]"
List<MyObjectRow> unwanted_objects = MyObject.find("id in (?,?,?,?,.....)",ids);
//remove the query results from the original arraylist
for(MyObjectRow o in unwanted_objects){
for(MyObject o1 in objects){
if(o1.getId() == o.getId()) objects.remove(o1);
}
}
第二种解决方案是查询数据库中每个对象是否存在,并将不存在的对象添加到结果数组中
ArrayList<MyObject> result_objects = new ArrayList<MyObject>();
boolean exist = false
for(MyObject o in objects){
exist = MyObject.find("EXIST( select 1 from my_object where id = ?)", o.getId());
if(!exist){
result_objects.add(o);
}
}
第一个解决方案只需要一个查询,但当循环遍历所有已建立的对象时,复杂性变为*n
第二个解决方案构造了n个db查询,但它的复杂性只有On
哪一个性能更好?您不知道数据库操作的效率。如果数据库是一个隐藏的b-树,那么该查询可能需要OLOGN。如果您的索引设置不正确,您可能正在查看该查询的性能。这里对效率的衡量也忽略了任何事务成本:启动与数据库的连接、处理查询和关闭与数据库的连接的成本。这是一个“固定”成本,如果不是必须的话,我不想在循环中这样做
使用第一种解决方案。我将使用选项1,并更改为使用映射,以提高从原始列表中删除查询结果的性能:
List<Integer> ids = new ArrayList<Integer>();
Map<Integer, MyObject> mapToInsert = new HashMap<Integer, MyObject>();
for(MyObject o in objects) {
//add the ids of the objects to possibly insert
ids.add(o.getId());
//using the id of the object as the key in the map
mapToInsert.put(o.getId(), o);
}
//retrieve the ids of the elements that already exist in database
List<MyObjectRow> unwanted_objects = MyObject.find("id in (?,?,?,?,.....)",ids);
//remove the query results from the map, not the list
for(MyObjectRow o in unwanted_objects){
mapToInsert.remove(o.getId());
}
//insert the values that still exist in mapToInsert
Collection<MyObject> valuesToInsert = mapToInsert.values();
使用选项1和集合或映射(而不是列表)将其更改为“开”。投票@Luiggimendoza感谢各位提供了简单但伟大的解决方案。您将搜索多少条记录?我不知道in子句中是否有一些限制,但如果您要搜索数百万个对象,它将根本不起作用。最好的解决方案可能是将两种解决方案结合起来。使用in子句进行搜索,但只搜索有限数量的os对象(最多1000个),并循环直到搜索完所有对象。您可以在循环之前打开连接,执行必要的语句,然后在循环之后关闭连接,其影响小于您描述的场景。选项1本身也不是正确的方法,但它比选项2好。是的,但我不知道他正在使用的ORM在幕后做什么。我也不知道,无论你使用的是什么ORM或JDBC之上的框架,概念都是一样的