2009-05-07 24 views
14

Estoy en el proceso de cambiar mi capa DAO del uso de la API Hibernate a usar una implementación pura API JPA. Parece que el método recomendado es usar createNamedQuery desde el administrador de entidades. Las consultas nombradas se almacenan en anotaciones en las clases de modelo/entidad. Esto simplemente no tiene sentido para mí. ¿Por qué definirías las consultas JPA en los objetos modelo pero las usarías en los DAO? ¿No sería más lógico utilizar createQuery desde el propio DAO y definir las consultas en el DAO o incluso simplemente definir las consultas con nombre en el mismo DAO?JPA por qué usar createNamedQuery

Para aquellos de ustedes que han implementado su capa DAO utilizando la API JPA, ¿cómo han definido sus consultas?

Respuesta

12

Uso consultas con nombre.

Hay dos razones para ello:

  1. Los pone en un lugar más central en lugar de dispersa en código con CreateQuery aleatorio() llama; y
  2. Los procesos de compilación pueden validar las consultas (realmente útiles).
+7

¿Por qué la ubicación central debería ser el objeto modelo frente al DAO que realmente lo está utilizando? – Ruggs

+2

Me olvidé de mencionar que estas consultas con nombre que normalmente pongo en la entidad. Si la consulta cruza varias entidades, solo elige la más relevante. – cletus

6

Tuve una experiencia completamente opuesta a la de cletus: no encontré ningún beneficio y también me resultó incómodo de usar. Las consultas triviales no tendrían ninguna diferencia sobre dónde definirlas, pero las consultas no triviales suelen ser difíciles de asociar con cualquier entidad individual, pero son sencillas con el método orientado a los negocios.

Si usa infraestructura más o menos sofisticada en DAO (para reutilización y coherencia), el uso de consultas con nombre tiende a complicar tanto la implementación como la legibilidad sin ofrecer ningún beneficio aparente.

La validación de consultas por proceso de compilación suena interesante. Me gustaría saber más de lo que realmente significa ... Mis consultas dejan poco margen de error ya que cada método DAO se prueba por unidades tanto como tiene sentido.

+1

También los encuentro incómodos y por eso propongo las preguntas. Tener un lugar central para las consultas tiene sentido para el mantenimiento, sin embargo, no sé si ponerlos en el objeto modelo tiene sentido. Si estoy manteniendo un DAO, primero voy al método DAO que necesita ser actualizado, ahora tengo que ir al objeto modelo solo para comenzar a ver la consulta. – Ruggs

+0

La validación es realmente bastante agradable. Uso eclipse para mi desarrollo y cuando escribí un par de consultas dejé la palabra clave AS desactivada y recibí errores durante la compilación. – Ruggs

+0

Debo añadir que normalmente no los uso para consultas triviales (por ejemplo, "seleccione p de Parte p donde nombre =: nombre"), solo consultas más complicadas. – cletus

2

No solo utilice consultas con nombre en todas partes, hay casos en que no son apropiadas, como cuando raramente se utilizarán consultas, entonces puede ser más eficiente cuando se construye según sea necesario.

Las consultas con nombre tienen más sentido cuando va a ser complejo y se ejecuta con frecuencia.

[Actualizado]

Puede escribir las consultas con nombre en la cartografía, en su lugar.

+0

¿Por qué la frecuencia de la consulta ejecutada lo hace un mejor candidato para ser una consulta con nombre. – Ruggs

+0

Las consultas nombradas se analizan una vez y se usan para siempre. Entonces, si escribimos una consulta incorrecta, arroja una excepción de inmediato. Las consultas que compila en el código se analizan todo el tiempo a menos que estén en caché. –

+0

Por cierto, el enlace dado sugiere lo mismo. http://www.oracle.com/technology/products/ias/toplink/doc/1013/main/_html/qryun008.htm –

10

Puedes echar un vistazo al Spring Data JPA. Le permite simplemente definir una interfaz y ejecutar consultas sin la necesidad de implementar la ejecución de forma manual.

Entidad:

@Entity 
@NamedQuery(id="User.findByLastname" query="from User u where u.lastname = ?1") 
public class User implements Persistable<Long> { 

    @Id 
    private Long id; 
    private String username; 
    private String lastname; 
    private int age; 
} 

Repositorio:

public interface UserRepository extends CrudRepository<User, Long> { 

    // Will trigger the NamedQuery due to a naming convention 
    List<User> findByLastname(String lastname); 

    // Will create a query from the methodname 
    // from User u where u.username = ? 
    User findByUsername(String username); 

    // Uses query annotated to the finder method in case you 
    // don't want to pollute entity with query info 
    @Query("from User u where u.age > ?1") 
    List<User> findByAgeGreaterThan(int age); 
} 

Configuración:

EntityManager em = Persistence.getEntityManagerFactory().createEntityManager(); 
JpaRepositoryFactory factory = new JpaRepositoryFactory(em); 

UserRepository repository = factory.getRepository(UserRepository.class); 

Como se puede ver se puede elegir entre diferentes maneras para obtener la consulta, para la ejecución del método .Si bien derivarlo directamente del nombre del método es factible para consultas simples, probablemente elija entre @NamedQuery (estándar JPA) o @Query (anotación Spring Data JPA) dependiendo de cuánto le gusta cumplir con los estándares.

Spring Data JPA le brinda soporte en varias otras esquinas de la implementación de la capa de acceso a datos, permite proporcionar implementaciones personalizadas para los métodos y se integra muy bien con Spring.

+0

La pregunta es sobre las soluciones JPA, no sobre qué API de persistencia usar. –

+3

La pregunta es: "Para aquellos de ustedes que han implementado su capa DAO usando la API JPA, ¿cómo han definido sus consultas?" y solo quería señalar una solución factible. Hades proporciona una alternativa más accesible para usar el EntityManager sencillo y está basado en JPA simple, por lo que no entiendo realmente su punto. –

+1

Creo que la respuesta y el razonamiento de Oliver están bien justificados. Personalmente creo que su ejemplo de Hades es muy interesante y responde a la pregunta. En realidad, creo que echaré un vistazo más profundo al marco ... :) –

2

Acepta el poder de y :) Si tienes una consulta que tiene sentido poner en el modelo, hazlo. Si no lo haces, no lo hagas. Podría ser incluso mejor preguntar "¿Por qué estás escribiendo DAO con JPS?" Si la respuesta es "Aislar mi código de la base de datos". Esto lo hace la biblioteca que implementa JPA. Si la respuesta es "aislar mi código de los cambios en la forma en que persisto", entonces JPA lo hace permitiéndote tener diferentes implementaciones. Utilizo objetos de consulta para consultas complejas, y sigo usando consultas con nombres siempre que sea posible, y me gusta el hecho de que las consultas con nombre se compilan, por lo que encuentro errores en ellas mucho más rápido. No tengo una capa DAO.