2009-09-23 6 views
1

Je rencontre un problème étrange en utilisant l'implémentation Toplink de JPA. J'écris une application autonome pour gérer les prêts.Java JPA OneToMany - Relation "plusieurs" non rafraîchissante

Je définis une classe LOAN qui a une relation OneToMany (bidirectionnelle) avec une classe NOTICE. J'ai créé une interface graphique pour afficher tous les avis pour un prêt particulier. Dans une autre partie de mon programme, je peux envoyer des avis en retard qui sont enregistrés comme un AVIS. Toutefois, lorsque j'essaie d'afficher tous les avis pour un prêt, l'avis tardif n'apparaît PAS. J'ai vérifié la base de données et une entrée a été enregistrée mais pour une raison quelconque, l'avis n'est pas retiré.

Ce n'est que lorsque je redémarre mon application que l'avis apparaît. Parce que j'ai défini une relation OneToMany, je ne fais pas moi-même une requête "directe" dans la base de données. Je laisse JPA gérer la récupération de tous les avis pour moi. En tant que correctif, j'ai créé une requête pour obtenir simplement tous les avis pour un prêt particulier. Cela marche. Cependant, je pensais en définissant la relation OneToMany entre les deux classes, cela devrait être géré pour moi. Il semble que quelque chose n'est pas rafraîchi correctement ... comme si une liste "plus ancienne" d'avis était utilisée au lieu de rafraîchir de la base de données?

+0

Pouvez-vous montrer votre prêt et sa cartographie @OneToMany et le code que vous essayez d'enregistrer? –

+0

Heureuse ma réponse a été en mesure de vous aider, j'ai rencontré un problème similaire à quelques reprises avec travailler avec différents ORM. Cela peut prêter à confusion, car les ORM prennent en charge un si grand nombre de parties du cycle de vie d'un objet qu'il est difficile de dire quand un petit code supplémentaire sera nécessaire. –

Répondre

4

Comment envoyez-vous l'avis de retard? Il doit y avoir une déclaration similaire à:

MyLoanInstance.listOfNotices.add(MyNoticeInstance); 

même si vous avez déjà un

MyNoticeInstance.setLoan(MyLoanInstance); 

déclaration

Sans cet appel, vous devrez soit complètement recharger l'instance que vous travaillez avec, ou redémarrez votre application.Eclipselink ne met pas automatiquement à jour (jusqu'au rechargement de tout) la collection du côté M d'une relation 1: M lorsque vous modifiez le côté 1, et ne met pas non plus à jour la référence du côté 1 de la relation 1: M si vous modifiez la collection du côté M

En note, vous devriez examiner EclipseLink, il a évolué à partir de ce qui était TopLink, vous devriez être capable d'échanger directement EclipseLink .jar avec TopLink .jar, si seulement pour recevoir quelques avertissements de dépréciation.

Eclipse Link

+0

Cela a fonctionné! Lorsque je "envoyais un avis en retard", je ne prenais soin que d'un côté de la relation 1: M - comme vous l'avez mentionné ci-dessus. Cependant, lorsque j'ai chargé le prêt pour voir les différents avis qui ont été émis, j'ai pensé que je rechargais complètement l'instance. Peut-être que je dois regarder de plus près mon code lorsque je charge l'instance de prêt. – Andre

+1

Merci - sauvé ma journée! – Hank

0

Je suppose que les éléments suivants

@Entity 
public class Loan { 

    private Integer id; 

    private List<Notice> noticeList; 

    @Id 
    @GeneratedValue 
    public Integer getId() { 
     return this.id; 
    } 

    @OneToMany(mappedBy="loan") 
    public List<Notice> getNoticeList() { 
     return noticeList; 
    } 

} 

@Entity 
public class Notice { 

    private Integer id; 

    private Loan loan; 

    @Id 
    @GeneratedValue 
    public Integer getId() { 
     return this.id; 
    } 

    @ManyToOne(fetch=FetchType.LAZY) 
    public Loan getLoan() { 
     return this.loan; 
    } 

} 

Vous avez dit

Dans une autre partie de mon programme, je peux envoyer des avis de retard qui est enregistré comme AVIS

Peut-être vous avoir deux instances EntityManager (une pour chaque partie de votre programme) afin que le dernier avis enregistré ne soit pas affiché car les deux entityManager ne partagent pas le même contexte de persistance t (On n'est pas au courant des changements survenus dans l'autre). Ce que vous pouvez faire est clair votre contexte de persistance, puis le récupérer à nouveau comme suit

Dans anthères partie de votre programme (après persistant votre avis) appelez

entityManager.flush(); 

Et quand vous voulez retrive un prêt et son Avis

entityManager.clear(); 

Query query = entityManager.creatQuery("from Loan l left join fetch l.noticeList where l.id = :id"); 

query.setParameter("id", yourLoanId); 

Vérifiez-le et dites-moi si cela fonctionne bien.

salutations

+0

Les classes d'entités Loan et Notice que vous décrivez ci-dessus sont à peu près les mêmes que celles que j'ai codées. Mon travail initial à mon problème était de créer une requête comme décrit ci-dessus mais je ne comprenais pas pourquoi faire - MyLoanInstance.getNoticeList() ne me donnait pas les mêmes résultats que la requête directement. Je pense que c'est un problème de "rafraîchissement" lié à deux instances d'entityManager comme vous le décrivez ci-dessus ... cependant, j'ai été capable de résoudre le problème avec la suggestion de Tnay. – Andre

1

Avez-vous essayé de faire une chasse d'eau sur votre gestionnaire d'entités après avoir persisté l'avis? [entityManager.flush()]

Questions connexes