Самый быстрый способ проверить, присутствует ли одна (или более) запись с данным идентификатором в нескольких таблицах - PullRequest
0 голосов
/ 01 сентября 2011

В моей прикладной БД для заданного объекта Foo с идентификатором String существует семь таблиц, каждая из которых содержит информацию об объекте Foo, а каждая из 7 таблиц имеет поле с идентификатором String объекта Foo (кака также много других полей с сохраненными данными).

В методе проверки качества мне нужно знать, какие идентификаторы (s) (экземпляры Foo Object) не содержат хотя бы одну строку (одну запись) хотя бы в однойиз семи таблиц.

Чтобы проверить, что я делал:

Boolean table1Ok = false;
Boolean table2Ok = false;
Boolean table3Ok = false;
Boolean table4Ok = false;
...

for (Foo instance : (Collection<Foo>) instancesToCheck)
{
   // for table 1
   try{
  Criteria crit = session.createCriteria(mappedObject1);
  ProjectionList projList = Projections.projectionList();
  projList.add(Projections.count("id"));
  crit.setProjection(projList);
  crit.add(Restrictions.eq("id", givenId));
  Long count = crit.uniqueResult();
  if (count>0){
    table1Ok = true;
  }
    }
catch ( HibernateException he){
    return new Long(0);
    }

   // table 2 similar code to table1
   // table 3 similar code to table1
   // table 4 similar code to table1
   // table 5 similar code to table1
   // table 6 similar code to table1
   // table 7 similar code to table1
}

Проблема заключается в том, что описанный выше подход действительно медленный, для моего приложения каждый счетчик строк таблицы занимает немногоболее 1 секунды, поэтому около 7-9 секунд, чтобы проверить один объект Foo (все 7 таблиц).

Я подозревал / надеялся, что это может быть связано с накладными расходами на создание критериев для каждой таблицы, и проверил, можно ли получить следующее предложение SQL быстрее (но я не смог):

select count(table1.id) as table1, 
       count(table2.id) as table2, 
       count(table3.id) as table3,
       count(table4.id) as table4, 
       count(table5.id) as table5, 
       count(table6.id) as table6,
       count(table7.id) as table7 
from table1, table2, table3, table4, table5, table6, table7 
where table1.id="GIVEN_ID" and 
      table1.id=table2.id  and 
      table1.id=table3.id  and 
      table1.id=table4.id  and
      table1.id=table5.id  and
      table1.id=table6.id  and
      table1.id=table7.id;

Теперь мой вопрос: как я могу улучшить скорость при проверке того, что для каждого объекта Foo есть (как минимум) одна запись в каждой из семи таблиц?

Если возможно,Я бы лучше использовал Критерии, чем Hibernate HQL.

Большое спасибо,

Guillem.

1 Ответ

0 голосов
/ 01 сентября 2011

Если вы сопоставили каждую из этих ассоциаций как ассоциации OneToOne JPA между сущностями, вы можете использовать следующий запрос (в HQL или критериях):

select t1.id, t2.id, ... from Foo f
left join f.table1 t1
left join f.table2 t2
...
where f.id = :theId

Затем проверьте, содержит ли возвращаемый массив идентификатор или ноль для каждой таблицы.

Если эти ассоциации не отображаются как ассоциации JPA, вы можете использовать собственный SQL-запрос, выполняющий те же действия, что и HQL-запрос выше:

select t1.id, t2.id, ... from Foo f
left join table1 t1 on f.id = t1.id
left join table2 t2 on f.id = t2.id
...
where f.id = :theId
...