2012-02-23 5 views
13

Así Im conseguir un número de instancias de una entidad en particular por idCargando varias entidades de Identificación de manera eficiente en Hibernate 4

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

esto genera una consulta SQL para cada ID, por lo que me ocurrió que yo haga esto en uno, pero no pude encontrar una forma de obtener múltiples entidades en una sola llamada, excepto al ejecutar una consulta. Así que escribí una consulta

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

pero si puedo activar el almacenamiento en caché de segundo nivel ¿no significa que mi viejo método sería capaz de devolver los objetos de la caché de segundo nivel (si se hubieran solicitado antes) pero mi la consulta siempre irá a la base de datos.

¿Cuál es la forma correcta de hacerlo?

+0

¿Alguna vez descubrió una forma de hacer esto? – FGreg

Respuesta

8

Lo que está pidiendo hacer aquí es que Hibernate haga un manejo de casos especial para su Criteria, que es mucho pedir.

Tendrá que hacerlo usted mismo, pero no es difícil. Con SessionFactory.getCache(), puede obtener una referencia del almacenamiento real de los objetos en caché. Hacer algo como lo siguiente:

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); 

A continuación, las canciones de la memoria caché consiguen recuperarse desde allí, y los que no lo son se estire con una sola select.

+0

gracias que tiene sentido –

0

Existe una diferencia entre el hibernación de segundo nivel de caché para hibernar el caché de consultas. El siguiente enlace lo explica muy bien: http://www.javalobby.org/java/forums/t48846.html

En pocas palabras, Si está utilizando la misma consulta muchas veces con los mismos parámetros, entonces puede reducir la base de datos realiza utilizando una combinación de ambos.

0

Otra cosa que podría hacer es ordenar la lista de identificadores, identificar subsecuencias de identificadores consecutivos y luego consultar cada una de esas subsecuencias en una sola consulta. Por ejemplo, dada List<Long> ids, haga lo siguiente (suponiendo que tiene una clase Pair en 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

Si sabe que existen los ID, puede utilizar load(..) para crear un proxy sin llegar a golpear la base de datos:

Devuelve la instancia persistente de la clase de entidad dada con el identificador dado, obteniendo el modo de bloqueo especificado, suponiendo que exista la instancia.

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

Una vez que acceda a un descriptor de acceso no identificador, Hibernate comprobar las memorias caché y vuelve a los DB, si es necesario, utilizando lotes ir a buscar si está configurado.

Si la ID no existe, se producirá una excepción ObjectNotFoundException una vez que se haya cargado el objeto. Esto podría ser en algún lugar de su código en el que no esperaría una excepción: al final, está usando un acceso sencillo. Por lo tanto, asegúrese al 100% de que el ID exista o al menos fuerce una ObjectNotFoundException en el momento en que lo esperaría, p. justo después de completar la lista.

Cuestiones relacionadas