2015-11-03 1 views
2

J'utilise les référentiels et entités JPA Spring dans une application. Maintenant, dans un aperçu de cette application, j'ai besoin d'étendre une de mes entités et de fournir également un référentiel étendu.@ Équivalent principal pour les référentiels JPA Spring auto-gérés

Pour tous les autres haricots que je dois remplacer/Prolonger je crée simplement une nouvelle implémentation et annoter avec @Primary il sera autowired au lieu de la mise en œuvre par défaut.

Pour les dépôts, cela ne fonctionne pas cependant. Je peux annoter le nouveau dépôt avec @Primary mais cela n'a aucun effet (les deux beans sont trouvés et ne peuvent donc pas être auto-gérés). Cela est logique car le référentiel est une interface et non une implémentation, l'implémentation est fournie dynamiquement par Spring.

Puis-je dire en quelque sorte printemps (via l'annotation sur le référentiel ou via la configuration) qui référentiel à utiliser? Ou dois-je faire une solution de contournement manuelle comme ceci Using @Primary in Spring Data JPA repositories ou devrais-je proposer une sorte de fournisseur de référentiel au lieu de autowiring?

Modifier pour rendre les choses plus claires: Disons que j'ai une entité A

@Entity 
public class A { 
    @Id 
    private long id; 
} 

et son dépôt

public ARepository extends Repository<A, Long> { 
} 

Maintenant, je l'étendre à l'entité B

@Entity 
public class B extends A { 
} 

public interface BRepository extends ARepository { 
} 

Normalement, selon la documentation, vous utilisez des référentiels comme ceci:

@Autowired 
private ARepository repository; 

Cela ne cependant fonctionne pas car il y a maintenant deux haricots de type ARepository. Pour les haricots que j'implémente moi-même j'utiliserais @Primary sur la classe d'extension mais pour les dépôts il n'y a pas d'implémentation de l'interface au moment de la compilation.

+0

Pourquoi l'extension d'entités et de référentiels pour cette entité nécessite-t-elle ce que vous décrivez dans votre second paragraphe. ... Peut-être que le paragraphe 2. devrait être reformulé - je (et cela ne semble être personne d'autre) comprendre ce que vous voulez faire/quel est votre problème. – Ralph

+0

@Ralph J'ai ajouté un exemple de code pour expliquer mon problème.Il y a aussi la question liée où j'essaie d'utiliser une usine de dépôt à la place de l'autowiring normal. –

+0

Maintenant je l'ai eu. - question interessante. – Ralph

Répondre

3

J'adapter l'idée de former cette réponse: https://stackoverflow.com/a/27549198/280244 et cet exemple git https://github.com/netgloo/spring-boot-samples/tree/master/spring-boot-springdatajpa-inheritance/src/main/java/netgloo/models

mettent en place un référentiel abstrait commun qui est marqué par @NoRepositoryBean

@NoRepositoryBean 
public interface AbstractARepository<T extends A> 
            extends Repository<T, Long> { 
    T findByName(String name); //or what ever your queries are 
} 

public ARepository extends AbstractARepository<A> { 
    //almost emtpy 
} 


public BRepository extends AbstractARepository<B> { 
    //queries that are special for B 
} 

Maintenant vous pouvez injecter ARepository et BRepository, et les deux sont de type save!

+0

Bien sûr, j'ai lu la question que vous avez liée auparavant, mais je pensais que ce n'était pas applicable à mon cas. Votre exemple de code est très intéressant. C'est une bonne solution si vous voulez utiliser 'A' avec' B'. Dans mon cas, cependant, je veux "redéfinir" l'entité de telle sorte que '@Autowire ARepository' renvoie effectivement une implémentation de' BRepository' de sorte que les entités soient créées comme 'B' et ne doivent pas être rechargées si je vouloir utiliser la fonctionnalité 'B'. Ce serait le comportement des beans '@ Primary' traditionnels. –

+0

@zero_cool: regardez de plus près ma suggestion. Le fait est que 'ARepository' et' BRepository' sont vides. Vous pouvez injecter ARepository ou BRepository par type. Bien sûr 'BRepository' ne s'étend pas' ARepository', mais je ne pense pas que cela soit nécessaire. – Ralph

+0

@zero_cool: Mais je ne chargerai plus jamais les entités 'B', alors il n'y a aucune raison d'avoir un' BRepository'. - Ou pourquoi en avez-vous besoin? – Ralph

1

Pour le compte rendu, il est possible d'ajouter @Primary support aux référentiels JPA comme suggéré ici Using @Primary in Spring Data JPA repositories

Ma mise en œuvre du code manquant:

private boolean isSpringDataJpaRepository(Class<?> beanClass) { 
     return JpaRepositoryFactoryBean.class.isAssignableFrom(beanClass); 
} 

Je pense que la réponse est @Ralph mieux à cause de la sécurité du type.