NativeQuery

Disponible

3.1 Présentation

Une autre chose utile dont je voudrais parler est NativeQuery . Comme vous le savez déjà, en utilisant NativeQuery, vous pouvez écrire des requêtes en SQL natif. Cependant, ce qui est encore plus intéressant, c'est que vous n'avez pas besoin d'utiliser le mappage de classe pour obtenir le résultat de la requête.

Je préfère vous montrer un exemple :

List<Object[]> persons = session.createNativeQuery("SELECT * FROM Person").list();

Dans cet exemple, nous ne transmettons pas une classe qui correspond aux lignes de résultat de la requête, mais nous utilisons simplement un tableau d'objets Object.

Cela peut être utile si vous souhaitez sélectionner uniquement quelques colonnes dans un tableau. Exemple:

List<Object[]> persons = session.createNativeQuery("SELECT id, name FROM Person").list();

for(Object[] person : persons) {
    Number id = (Number) person[0];
    String name = (String) person[1];
}

Ceci est quelque peu similaire à l'approche JDBC lorsque vous obtenez un objet ResultSet et lisez les données de ses lignes.

Cependant, Hibernate propose différentes manières de rendre cela plus fiable. Par exemple, vous pouvez spécifier le type de colonnes que vous souhaitez soustraire. Exemple:

Query<Object[]> query = session.createNativeQuery("SELECT id, name FROM Person");
query.addScalar("id", StandardBasicTypes.LONG);
query.addScalar("name", StandardBasicTypes.STRING);
List<Object[]> persons = query.list();

for(Object[] person : persons) {
    Long id = (Long) person[0];
    String name = (String) person[1];
}

3.2 Cartographie des entités

Vous pouvez également spécifier explicitement la classe que Hibernate doit utiliser lors de l'analyse du résultat de NativeQuery . Cela peut se faire de différentes façons.

Query<Person> query = session.createNativeQuery("SELECT * FROM Person")
    .addEntity(Person.class);
    .list();

Et bien sûr, le bon vieux format que vous connaissez :

Query<Person> query = session.createNativeQuery("SELECT * FROM Person", Person.class).list();

La première approche est l'approche native Hibernate et la seconde est l'approche JPA. L'approche JPA est plus pratique et concise, car cette norme a été inventée après l'existence d'Hibernate pendant de nombreuses années. Et Hibernate a évolué et a été contraint de supporter les anciennes approches afin de maintenir la compatibilité avec ses anciennes versions.

Soit dit en passant, grâce à son approche, Hibernate vous permet de connecter non pas une classe au mappage des résultats de la requête, mais plusieurs classes. Exemple:

List<Phone> results = session.createNativeQuery(
    "SELECT {ph.*}, {pr.*}" +
    "FROM Phone ph" +
    "JOIN Person pr ON ph.person_id = pr.id")
.addEntity("ph", Phone.class)
.addJoin("pr", "ph.person")
.list();

for (Phone. phone : results) {
           	assertNotNull( phone.getPerson().getName() );
}

Cette approche utilisant NativeQuery peut être utilisée pour accélérer la sélection des données de la base de données. Si vous savez que vous n'avez pas besoin de certaines colonnes, vous pouvez les laisser de côté dans la requête.

Vous pouvez également charger toutes les entités enfants en même temps, même si Hibernate veut utiliser Cache ou le mécanisme LazyLoading . De plus, vos entités enfants peuvent avoir de nombreuses colonnes dans la base de données et vous ne pouvez sélectionner que certaines d'entre elles.

3.3 Cartographie DTO

Hibernate vous permet également d'utiliser des classes non-Entity pour mapper le résultat. Classes qui n'ont pas d'annotations et ne sont mappées à aucune table.

Exemple:

public class PersonSummaryDTO {
    private Number id;
    private String name;

    public Number getId() {
    	return id;
    }

    public void setId(Number id) {
    	this.id = id;
    }

    public String getName() {
    	return name;
    }

    public void setName(String name) {
    	this.name = name;
	}
}

List<PersonSummaryDTO> dtos = session.createNativeQuery(
    "SELECT p.id as \"id\", p.name as \"name\" FROM Person p")
.setResultTransformer(Transformers.aliasToBean(PersonSummaryDTO.class) )
.list();

Puisqu'il n'y a pas d'annotations dans la classe PersonSummaryDTO, les noms des colonnes de la requête SQL doivent correspondre exactement aux noms des champs de la classe PersonSummaryDTO.

Cela peut être très utile si vous lisez des données à partir d'une base de données externe à laquelle votre application est connectée uniquement en mode lecture seule. Autrement dit, vous avez eu accès à des tables contenant plus de 50 colonnes, elles stockent les données sous une forme dénormalisée pour accélérer la sélection.

Ou disons que quelqu'un a décidé de stocker la hiérarchie des classes dans une table, et en cinq ans cette table a tellement grandi que le diable va se casser la jambe. Vous devez sélectionner quelques colonnes de ce tableau (ID et nom d'utilisateur) et les donner au client.

Je pense que vous comprenez, mais si vous voulez approfondir ce sujet, vous pouvez en savoir plus sur le lien :

Requêtes SQL natives

Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires