En quoi Spring Data JPA diffère-t-il d'Hibernate pour les grands projets?

129

J'ai du mal à décider si je devrais rester avec Hibernate pour un nouveau projet, ou me mouiller les pieds avec JPA et la nouvelle implémentation de Spring Data.

Le framework Spring Data est-il destiné aux grands projets ou aux petits projets avec des exigences de requête modestes?

Bien que je vois certainement l'avantage de la réduction du code en utilisant l' @Queryannotation, que faites-vous pour les requêtes dynamiques? Qu'en est-il lorsque vous souhaitez implémenter une méthode save () assez complexe?

La documentation dit de créer une interface personnalisée et une implémentation que votre référentiel principal implémente, mais que faire si vous avez besoin d'accéder à des super méthodes sur le référentiel crud lui-même? Le référentiel crud implémente le référentiel personnalisé - et non l'inverse. Cela semble être un design étrange.

Je ne sais pas si ce cadre répondra aux défis des applications complexes et volumineuses. Je n'ai jamais rencontré beaucoup de problèmes avec Hibernate, et j'envisage de m'en tenir au bon vieux fiable plutôt que d'utiliser Spring Data JPA.

Que devrais-je faire? Quelles complications et quels coûts imprévus vais-je rencontrer si j'utilise Spring Data JPA?

egervari
la source
1
Autant que je sache, cela fait peu de différence. Choisissez celui avec lequel vous êtes le plus à l'aise. Pourquoi le débat?
duffymo
1
Je suis évidemment beaucoup plus à l'aise avec Hibernate, mais si je peux faire les mêmes choses et être plus productif, je préférerais adopter les nouvelles approches. Cependant, si Hibernate est toujours plus puissant et que je vais rencontrer beaucoup moins de problèmes, alors c'est quelque chose que j'aimerais savoir.
egervari
3
JPA est une généralisation d'ORM qui utilise Hibernate comme l'une des nombreuses implémentations. Quels pouvoirs attribuez-vous à l'un par rapport à l'autre? JPA est une norme, mais je vois peu de différence entre les deux. Dans l'intérêt d'une divulgation complète, je dirai que je ne me soucie pas de l'un ou l'autre. Les deux génèrent du SQL pour vous. Je préfère l'écrire moi-même. ORM n'est pas pour chaque problème et chaque utilisateur.
duffymo
1
Je suis d'accord. Quand il s'agit de JPA ou Hibernate uniquement, je choisirais Hibernate à chaque fois. Honnêtement, je n'aime pas tellement l'implémentation JPA en elle-même. La prise en charge de l'IDE dans IDEA est encore assez mauvaise, et elle se plaindra si les mappages ne sont pas corrects au démarrage de l'application plutôt que de laisser les tests unitaires s'exécuter. Il y a beaucoup d'autres pinaillages que j'ai avec JPA. J'apprécie en fait les anciens fichiers de mappage XML Hibernate. Cela a l'avantage de rendre mes objets beaucoup moins encombrés aussi. Spring Data JPA offre de nombreuses nouvelles fonctionnalités, alors je me demandais finalement si cela valait la peine de changer.
egervari
3
"Spring Data" n'est pas une implémentation de JPA, ou quoi que ce soit. Il prend simplement une implémentation JPA existante et simplifie ce que vous lui fournissez. La mise en œuvre de JPA fait toujours tout le travail sous les couvertures
Neil Stockton

Réponses:

104

Alors, spring-datafaites un peu de magie supplémentaire qui aide avec les requêtes complexes. C'est étrange au début et vous l'ignorez totalement dans la documentation mais c'est vraiment puissant et utile.

Cela implique de créer un Repository`RepositoryImpl ' personnalisé et personnalisé et d'indiquer à Spring où le trouver. Voici un exemple:

Classe de configuration - pointez sur votre configuration xml encore nécessaire avec une annotation pointant vers votre package de référentiels (il recherche *Implautomatiquement les classes maintenant):

@Configuration
@EnableJpaRepositories(basePackages = {"com.examples.repositories"})
@EnableTransactionManagement
public class MyConfiguration {
}

jpa-repositories.xml - indique Springoù trouver vos dépôts. Dites également Springde rechercher des référentiels personnalisés avec le CustomImplnom de fichier:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<jpa:repositories base-package="com.example.repositories" repository-impl-postfix="CustomImpl" />

</beans>

MyObjectRepository- c'est ici que vous pouvez placer des méthodes de requête annotées et non annotées. Notez comment cette interface de référentiel étend Customcelle:

@Transactional
public interface MyObjectRepository extends JpaRepository<MyObject, Integer>, MyObjectRepositoryCustom {

    List<MyObject> findByName(String name);

    @Query("select * from my_object where name = ?0 or middle_name = ?0")
    List<MyObject> findByFirstNameOrMiddleName(String name);
}

MyObjectRepositoryCustom - des méthodes de référentiel plus complexes et ne pouvant être manipulées avec une simple requête ou une annotation:

public interface MyObjectRepositoryCustom {

    List<MyObject> findByNameWithWeirdOrdering(String name);
}

MyObjectRepositoryCustomImpl- où vous implémentez réellement ces méthodes avec un autowired EntityManager:

public class MyObjectRepositoryCustomImpl implements MyObjectRepositoryCustom {

    @Autowired
    private EntityManager entityManager;

    public final List<MyObject> findByNameWithWeirdOrdering(String name) {
        Query query = query(where("name").is(name));
        query.sort().on("whatever", Order.ASC);
        return entityManager.find(query, MyObject.class);
    }
}

Étonnamment, tout cela est réuni et les méthodes des deux interfaces (et de l'interface CRUD, que vous implémentez) apparaissent toutes lorsque vous le faites:

myObjectRepository.

Tu verras:

myObjectRepository.save()
myObjectRepository.findAll()
myObjectRepository.findByName()
myObjectRepository.findByFirstNameOrMiddleName()
myObjectRepository.findByNameWithWeirdOrdering()

Cela fonctionne vraiment. Et vous obtenez une interface pour les requêtes. spring-dataest vraiment prêt pour une grande application. Et plus vous pouvez intégrer de requêtes simples ou d'annotations, mieux vous vous portez.

Tout cela est documenté sur le site Spring Data Jpa .

Bonne chance.

sbzoom
la source
4
C'est en fait ce que j'ai essayé et cela fonctionne dans une certaine mesure. Le problème que j'ai eu est que se passe-t-il si vous voulez remplacer save ()? Par exemple, imaginez que vous enregistrez un blog et que vous souhaitez traiter / enregistrer les balises qui lui sont associées dans la méthode save () car le mettre dans un service n'a pas de sens. C'est facile à faire avec Hibernate brut, mais je ne vois pas de bon moyen de faire avec Spring JPA. Je vais cependant marquer votre réponse comme correcte parce qu'elle est correcte. C'est essentiellement ce que vous pouvez faire avec Spring Data JPA. Je pense que je vais m'en tenir à Hibernate. Cette réponse aidera certainement les autres.
egervari
8
Vous pouvez implémenter votre propre JpaRepository-> MyJpaRepository. Vous devez également créer un MyJpaRepositoryFactoryBeanmais si vous configurez tout correctement, vous pouvez remplacer la méthode .save (). Voici les documents JPA de Spring Data: static.springsource.org/spring-data/data-jpa/docs/current/ ... N'abandonnez pas pour l'instant!
sbzoom
@Picrochole comment interprétez-vous le «niveau inférieur de l'application»? Le service, qui appelle DAO, est-il inférieur au niveau?
Rumid
12

J'ai utilisé Spring Data JPA dans des projets petits et grands avec des requêtes simples. Le principal avantage est de ne même pas avoir à utiliser l' @Queryannotation. Il n'y a rien dans Spring Data qui vous empêche de l'utiliser dans de grands projets et le QueryDSLsupport récent pourrait vous aider. Voici un exemple d'utilisation de QueryDSL pour cibler Hibernate.

Si vous prévoyez des requêtes complexes et que vous vous sentez à l'aise d'utiliser des objets Hibernate sans JPA, je pense qu'une combinaison alternative pourrait être d'avoir les simples Spring Data à Repositorycôté de celles basées sur Hibernate complexes avec les méthodes spécifiques dont vous pourriez avoir besoin. Cela peut être moins fastidieux que de transformer une implémentation Hibernate en une structure Spring Data JPA.

madth3
la source
2
Je pense que je préfère utiliser la même API cohérente pour les requêtes plutôt que de mélanger et de faire correspondre le même projet. Je n'ai toujours pas trouvé de bonne solution pour les trucs complexes de jpa de données de printemps, et comme il y a pas mal de pinaillages avec jpa en général, je pense que je serai peut-être plus heureux d'accepter l'hibernation comme mon orm. J'aurai beaucoup de requêtes complexes et je ne peux pas me permettre d'avoir un mélange 40/60. Cela ne vaut pas la peine pour moi :(
egervari
1
Vous pouvez également utiliser Querydsl directement sans Spring Data, ce qui vous donne une seule couche de requête puissante au-dessus de JPA.
Timo Westkämper
4

Spring JPA vous fournira beaucoup d'abstraction de l'écriture de SQL et même de HQL en utilisant la déclaration de méthode de requête. Spring JPA brille avec sa génération de requêtes, mais lorsque vous souhaitez une solution purement de mise en veille prolongée, vous pouvez la personnaliser selon vos besoins, car Spring JPA est toujours basé sur la mise en veille prolongée. Consultez la documentation http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html pour plus d'informations.

FOO
la source