2012-02-23 3 views
13

Так Im получая количество экземпляров конкретного объекта по идентификаторуЗагрузка нескольких объектов по идентификатору эффективно в Hibernate 4

for(Integer songId:songGroup.getSongIds()) 
{ 
    session = HibernateUtil.getSession(); 
    Song song = (Song) session.get(Song.class,id); 
    processSong(song); 
} 

это генерирует SQL-запрос для каждого идентификатора, поэтому ocurred мне, что я должен делать это в одном, но я не мог найти способ получить несколько объектов в одном вызове, кроме как запустив запрос. Поэтому я написал запрос

return (List) session.createCriteria(Song.class) 
     .add(Restrictions.in("id",ids)).list(); 

но если включить кэширование 2-го уровня не значит, что мой старый метод был бы в состоянии вернуть объекты из кэша второго уровня (если они были запрошены ранее), но мой запрос всегда будет обращаться к базе данных.

Какой правильный способ сделать это?

+0

Вы когда-нибудь выяснили, как это сделать? – FGreg

ответ

8

Что вы хотите сделать здесь, чтобы Hibernate выполнял специальную обработку дела для ваших критериев, что очень много, чтобы спросить.

Вам нужно будет сделать это самостоятельно, но это не сложно. Используя SessionFactory.getCache(), вы можете получить ссылку на фактическое хранилище для кешированных объектов. Сделайте что-то вроде следующего:

for (Long id : allRequiredIds) { 
    if (!sessionFactory.getCache().containsEntity(Song.class, id)) { 
    idsToQueryDatabaseFor.add(id) 
    } else { 
    songs.add(session.get(Song.class, id)); 
    } 
} 

List<Song> fetchedSongs = session.createCriteria(Song.class).add(Restrictions.in("id",idsToQueryDatabaseFor).list(); 
songs.addAll(fetchedSongs); 

Затем песни из кэша получить извлеченный оттуда, и те, которые не втянуты с одной select.

+0

спасибо, что имеет смысл –

0

Существует разница между спящим кэшем второго уровня спящего режима для спящего режима кэша запросов. Следующая ссылка объясняет это очень хорошо: http://www.javalobby.org/java/forums/t48846.html

В двух словах, Если вы используете один и тот же запрос много раз с теми же параметрами, вы можете уменьшить базу хитов, используя комбинацию обоих.

0

Еще одна вещь, которую вы могли бы сделать - сортировать список идентификаторов и идентифицировать подпоследовательности последовательных идентификаторов, а затем запрашивать каждую из этих подпоследовательностей в одном запросе. Например, при List<Long> ids, выполните следующие действия (при условии, что у вас есть класс Pair в Java):

List<Pair> pairs=new LinkedList<Pair>(); 
List<Object> results=new LinkedList<Object>(); 
Collections.sort(ids); 
Iterator<Long> it=ids.iterator(); 

Long previous=-1L; 
Long sequence_start=-1L; 
while (it.hasNext()){ 
    Long next=it.next(); 

    if (next>previous+1) { 
     pairs.add(new Pair(sequence_start, previous)); 
     sequence_start=next; 
    } 
    previous=next; 
} 
pairs.add(new Pair(sequence_start, previous)); 

for (Pair pair : pairs){ 
    Query query=session.createQuery("from Person p where p.id>=:start_id and p.id<=:end_id"); 
    query.setLong("start_id", pair.getStart()); 
    query.setLong("end_id", pair.getEnd()); 

    results.addAll((List<Object>)query.list()); 

} 
1

Если вы знаете, что идентификаторы существуют, вы можете использовать load(..) создать прокси-сервер фактически не ударять БД:

Возвращает постоянный экземпляр данного класса сущности с данным идентификатором, получая указанный режим блокировки, предполагая, что экземпляр существует.

List<Song> list = new ArrayList<>(ids.size()); 
for (Integer id : ids) 
    list.add(session.load(Song.class, id, LockOptions.NONE)); 

После получения доступа к не-идентификатору аксессора, Hibernate будет проверять кэша и при необходимости возврата к БД, используя пакет сгрузить, если настроено.

Если идентификатор не существует, объект ObjectNotFoundException будет возникать после загрузки объекта. Это может быть где-то в вашем коде, где вы бы не ожидали исключения - в конце вы используете простой аксессор. Таким образом, либо на 100% убедитесь, что ID существует, либо, по крайней мере, вынуждает ObjectNotFoundException раньше, когда вы ожидаете его, например. сразу после заполнения списка.

Смежные вопросы