2010-12-10 66 views
2

J'ai un problème avec l'écriture par lots dans eclipselink lorsque je mets à jour une propriété d'entité qui lie à une autre entité.JPA/Eclipselink entité de mise à jour par lots de mauvaise performance sur les changements de relation ManyToOne

J'ai une entité de titulaire de carte avec une relation @ManyToOne avec l'entité de carte.

@Entity 
@Table(name = "...") 
@NamedQueries({...}) 
public class Cardholder implements Serializable { 
    ... 
    @JoinColumn(name = "card_number", referencedColumnName = "...") 
    @ManyToOne(fetch=FetchType.LAZY) 
    private Card card; 
} 

et une carte avec relation @OneToMany avec titulaire

@Entity 
@Table(name = "cms_card") 
@NamedQueries({...}) 
public class Card implements Serializable { 
    @OneToMany(mappedBy = "card") 
    private List<Cardholder> cardholderList; 
} 

J'ai déjà Liste des enfants (persisté titulaires de carte). Maintenant, je veux ajouter une carte à eux, donc: // cardholderList est une liste d'entités gérées.

for (Cardholder cardholder : cardholderList) { 
    Card newCard = new Card(); 
    ... 
    cardholder.setCard(newCard); 
    List<Cardholder> cardCardholders = new ArrayList<Cardholder>(); 
    cardCardholders.add(cardholder); 
    newCard.setCardholderList(cardCardholders); 
    cardsToBePersisted.add(newCard); 
    ++i; 
} 

J'ai configuré mon persistence.xml à utiliser l'écriture par lots, mais la performance est horriblement lent pour + -15000 mise à jour de la liste. Maintenant, quand je vérifie dans le SQL généré, je trouve que EclipseLink crée un lot pour une requête, son comme:

FINER: Begin batch statements 
FINE: INSERT INTO cms_card (card_number, status, chip_serial_number, dwh_status, valid_until, card_holder_id, file_perso_history_id, feedback_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) 
FINE:   bind => [9030002005890011, ACTIVE, null, false, 2015-12-10, null, 241, null] 
FINER: End Batch Statements 
FINER: Begin batch statements 
FINE: UPDATE cms_cardholder SET card_number = ? WHERE (id = ?) 
FINE:   bind => [9030002005890011, 176075] 
FINER: End Batch Statements 
FINER: Begin batch statements 
FINE: INSERT INTO cms_card (card_number, status, chip_serial_number, dwh_status, valid_until, card_holder_id, file_perso_history_id, feedback_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) 
FINE:   bind => [9030002005889908, ACTIVE, null, false, 2015-12-10, null, 241, null] 
FINER: End Batch Statements 

Je pense que cela est parce que je mets une nouvelle propriété parent (carte) aux enfants existants. J'essaie aussi de jouer avec l'inversion de la relation parent-enfant (titulaire de carte-> carte au lieu de carte-> titulaire de carte). L'insertion par lot est correcte après avoir inversé la relation dans l'entité et la base de données, mais Eclipselink interroge toujours la base de données (SELECT * de la carte où cardholder.id =?), Donc pour 15000 enregistrement j'ai l'instruction 15000 select. Mieux qu'au dessus, mais toujours très très lent.

Y a-t-il une erreur dans la configuration de l'écriture par lots? Merci beaucoup.

+0

Pouvez-vous également publier le code EntityManager? Emettez-vous un em.flush() à tout moment? –

Répondre

0

Je ne suis pas vraiment sûr de la cause de votre problème, mais je vous conseille de faire ceci:

Si j'ai une situation OneToMany et ManyToOne, et il implique beaucoup de données de collecte, je vais éviter d'utiliser la collection ajouter des détails, car cela pourrait déclencher le remplissage de la collection quand ce n'est pas nécessaire, ce qui pourrait être la source d'un problème de performance.

Un exemple simple qui aidera à illustrer ce que je voulais dire: Considérez 2 entités de l'équipe et le joueur, Une équipe a une liste de joueur (un à plusieurs) Un joueur a une équipe (plusieurs à un)

Chaque fois que je veux ajouter un nouveau joueur, je le ferais:

équipe team = getTeamFromDbUsingEntityManager (teamid); Joueur joueur = nouveau joueur(); ... player.setTeam (équipe); entityManager.persist (lecteur);

Notez qu'il ne fait pas team.addPlayer (lecteur); ce qui signifie que vous ne touchez pas à la collection.

1

Quelles sont toutes les relations dans la carte et le titulaire de la carte?

Vous semblez avoir un cycle entre les deux classes, EclipseLink doit donc émettre la mise à jour pour résoudre le cycle.

Vous avez un card_holder_id dans votre carte et un card_number dans votre CardHolder? Pourquoi avez-vous une clé foriegn dans les deux tables à l'autre? Si vous corrigez votre cycle, les inserts peuvent être regroupés et permettre un dosage optimal.

Vous ne savez pas ce que vous faites pour obtenir la sélection? Ce sont de nouveaux objets sont-ils notés? Ou mettez-vous à jour aussi?