2009-06-18 14 views
0

Wir haben eine sehr einfache Methode, die "findById" verwendet.Hibernate findById findet keine Datensätze, die zuvor gefunden wurden

public Cart getCart(long cartId) { 
    Cart cart = null; 

    try { 

     dbSession.beginTransaction(); 
     cart = (Cart)dbSession.findById(Cart.class, cartId); 
     dbSession.commitTransaction(); 

     if (logger.isDebugEnabled()) { 
      logger.debug("The getCart call committed successfully"); 
     } 

    } finally { 
     if (dbSession.needsRollback()) { 
      dbSession.rollbackTransaction(); 
     } 
    } 

    logGetCartResults(cartId, cart); 

    return cart; 
} 

private void logGetCartResults(long cartId, Cart cart) { 
    if (logger.isDebugEnabled()) { 

     StringBuffer message = new StringBuffer("Cart id "); 
     message.append(cartId) 
       .append(" was "); 

     if (cart != null) { 
      message.append("not "); 
     } 

     message.append("null"); 

     logger.debug(message.toString()); 
    } 
} 

Diese Methode wird manchmal von einer anderen Anwendung in schneller Folge aufgerufen (es ist im Grunde ein anderes System, das einen Wagen lädt). Wir haben einen Thread, der einen Einkaufswagen erstellt, den Datensatz in die Datenbank schreibt und dann die Anwendung einmal für jedes Element aufruft, das in die Datenbank gehen muss. Obwohl die andere Anwendung nacheinander sendet und auf eine Antwort wartet, ruft Tomcat diese auf separaten Threads ab.

Wir sehen erste Anrufe zu "getCart" tatsächlich in der Lage, den Datensatz zu finden. Gelegentlich schlägt ein Anruf fehl, auch nachdem andere Anrufe erfolgreich waren. Hier ist ein Teil des Protokolls, um mehr Kontext zur Verfügung zu stellen:

DEBUG 2009-06-18 16:10:57,145 [http-8080-Processor20] com.eroi.managers.impl.DefaultPurchaseManager: Looking for cartId 49 
    DEBUG 2009-06-18 16:10:57,146 [http-8080-Processor20] com.eroi.persistors.impl.DefaultPurchasePersistor: The getCart call committed successfully 
    DEBUG 2009-06-18 16:10:57,146 [http-8080-Processor20] com.eroi.persistors.impl.DefaultPurchasePersistor: Cart id 49 was not null 
    ... 
    DEBUG 2009-06-18 16:10:57,522 [http-8080-Processor14] com.eroi.managers.impl.DefaultPurchaseManager: Looking for cartId 49 
    DEBUG 2009-06-18 16:10:57,523 [http-8080-Processor14] com.eroi.persistors.impl.DefaultPurchasePersistor: The getCart call committed successfully 
    DEBUG 2009-06-18 16:10:57,523 [http-8080-Processor14] com.eroi.persistors.impl.DefaultPurchasePersistor: Cart id 49 was not null 
    ... 
    DEBUG 2009-06-18 16:10:57,934 [http-8080-Processor10] com.eroi.managers.impl.DefaultPurchaseManager: Looking for cartId 49  
    DEBUG 2009-06-18 16:10:57,934 [http-8080-Processor10] com.eroi.persistors.impl.DefaultPurchasePersistor: The getCart call committed successfully 
    DEBUG 2009-06-18 16:10:57,934 [http-8080-Processor10] com.eroi.persistors.impl.DefaultPurchasePersistor: Cart id 49 was null 

So. Thread 20, 14 waren erfolgreich, aber Thread 10 konnte den Datensatz nicht finden. Was gibt? Wir haben kein Caching (außer dem standardmäßigen Caching auf der ersten Ebene).

<hibernate-configuration> 
    <session-factory> 
     <property name="current_session_context_class">thread</property> 
     <property name="hibernate.connection.datasource">java:/comp/env/jdbc/ourdb</property> 
     <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 
    </session-factory> 
</hibernate-configuration> 

Einsicht, Ideen oder. . . nun, alles ist willkommen.

+0

Das riecht nach einem Session/Transaction-Handling-Problem, aber Ihre Code-Fragmente zeigen uns nicht, wie Sie diese Ressourcen verwalten. Zum Beispiel, wo und wann holen Sie die Sitzung? Wenn dbSession ein Hibernate-Sitzungsobjekt ist, gibt es keine commitTransaction() -Methode für die Sitzung. Schließlich geben Sie eine explizite Transaktionsisolation an beliebiger Stelle an? – skaffman

Antwort

0

Dies lag an einem Transaktionsfehler in unserem Code. Obwohl es so aussah, als ob unser Code in jeder Anfrage eine neue Sitzung startete, stellten wir fest, dass diese neuen Sitzungen gelegentlich keine neue JDBC-Verbindung erhielten. Wir haben festgestellt, wo wir keine Transaktion getätigt haben. Aufgrund der Art und Weise, wie wir Calls verwalten, um zu beginnen und zu committen, haben wir im Wesentlichen eine lang laufende Transaktion erstellt, die nie abgeschlossen wurde (und sich nicht wie erwartet verhalten hat).

0

Ist es möglich, dass zu der Zeit Thread 10 seine Transaktion startet, dass die ID noch nicht eine vollständig festgeschriebene Transaktion ist? Also im Grunde frage ich - wenn Sie einen Warenkorb 49 bereits in der Datenbank haben (sagen Sie am Anfang des Programms) kann der Thread immer noch dieses Problem haben?

+0

Es scheint so, aber es gibt Threads, die dieselbe findById mit denselben Argumenten aufrufen, die das Objekt zurückgeben. Ich bin zuversichtlich, dass das erste "Einfügen" festgeschrieben ist. Aber wenn ein "update" nicht festgeschrieben wird (oder gerade festgeschrieben wird), könnte es dann so aussehen, als ob kein Ereignis für andere Transaktionen existiert? –

+0

Ich glaube nicht, dass ein Update das Objekt verstecken könnte, ich würde denken, es würde nur "veraltet" erscheinen, vorausgesetzt, Sie haben den Schlüssel nicht geändert ... Beachten Sie, dass ich eine Menge von jdbc (und jetzt überwintern, da wir über) arbeiten, und ich habe ähnliche Probleme in unserem Programm gesehen. Es stellte sich immer heraus, dass das Problem so war, wie ich es beschrieben hatte, es war nur eine Frage des Synchronisationsproblems. – Petriborg

Verwandte Themen