2010-12-10 9 views
2

Ich habe Probleme mit Batch-Schreiben in Eclipselink, wenn ich eine Entität Eigenschaften aktualisieren, die mit anderen Entität verknüpfen.JPA/Eclipselink schlechte Leistung Batch-Update-Einheit auf ManyToOne Beziehung ändert

Ich habe eine Karteninhaber-Entity mit @ManyToOne Beziehung mit Card Entity.

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

und eine Karte mit @OneToMany Beziehung mit Karteninhaber

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

Ich habe bereits Liste des Kindes (Karteninhaber beibehalten). Jetzt möchte ich ihnen eine Karte hinzufügen, so: // cardholderList ist eine Liste der verwalteten Entitäten.

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; 
} 

Ich baute mein persistence.xml Batch-Schreiben zu verwenden, aber die Leistung ist schrecklich langsam für + -15000 Liste zu aktualisieren. Nun, wenn ich in der generierten SQL überprüfen, fand ich, dass Eclipse eine Charge für eine Abfrage schafft, sein wie:

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 

Ich denke, das ist, weil ich ein neues übergeordnetes Objekt (Karte) an bestehenden Kinder eingestellt.

Ich versuche auch mit der Umkehrung der Eltern-Kind-Beziehung (Karteninhaber-> Karte statt Karte-> Karteninhaber) zu spielen. Batch einfügen ist korrekt, nachdem ich die Beziehung in Entität und Datenbank umkehren, aber Eclipselink würde die Datenbank abfragen (SELECT * von der Karte, wo cardholder.id =?), So für 15000 Datensatz habe ich 15000 Select-Anweisung. Besser als oben, aber immer noch sehr, sehr langsam.

Gibt es einen Fehler beim Batch-Schreiben? Vielen Dank.

+0

Können Sie den EntityManager-Code auch posten? Erteilen Sie zu irgendeinem Zeitpunkt eine em.flush()? –

Antwort

0

Im nicht wirklich sicher über die Ursache des Problems, aber ich würde dies empfehlen tun:

Wenn ich eine OneToMany und manyToOne Situation haben, und es beinhaltet viele Sammlungsdaten, ich werde vermeiden, dass die Sammlung mit um Details [s] hinzuzufügen, da dies das Auffüllen der Sammlung auslösen könnte, wenn dies nicht notwendig ist, was die Ursache für das Leistungsproblem sein könnte.

Ein einfaches Beispiel, das veranschaulicht, wird dazu beitragen, was ich meinte: Betrachten wir zwei Entitäten des Teams und Spieler, A Team hat eine Liste der Spieler (one to many) Ein Spieler hat ein Team (viele zu eins)

Immer wenn ich einen neuen Player hinzufügen möchte, würde ich tun:

Team team = getTeamFromDbUsingEntityManager (teamId); Spieler Spieler = neuer Spieler(); ... player.setTeam (Team); entityManager.persist (Spieler);

Beachten Sie, dass es nicht tut.addPlayer (Player); was bedeutet, dass Sie die Sammlung nicht berühren.

1

Was sind alle Beziehungen in der Karte und Karteninhaber?

Sie scheinen einen Zyklus zwischen den beiden Klassen zu haben, daher muss EclipseLink das Update ausgeben, um den Zyklus zu lösen.

Sie haben eine card_holder_id in Ihrer Karte und eine card_number in Ihrem CardHolder? Warum haben Sie einen Fremdschlüssel in beiden Tabellen zum anderen? Wenn Sie Ihren Zyklus fixieren, können die Einsätze gruppiert werden und ermöglichen eine optimale Dosierung.

Nicht sicher, was Sie tun, um die Auswahl zu bekommen? Das sind neue Objekte, sind sie notiert? Oder aktualisierst du auch?