2016-11-08 5 views
0

Ich habe eine SpringBoot-Anwendung, die SpringData verwendet, um Daten auf einer Oracle-DB zu persistieren, und spring-boot-starter-activemq, um JMS-Warteschlangen zu verarbeiten.Wie die Hibernate-Sitzung der JmsListener-Methode zugeordnet wird

Ich belichte einen DELETE Rest WebService, der eine Weile dauert. Und ich möchte nicht, dass meine Benutzer an der Antwort hängen bleiben.

Also habe ich eine Methode hinzugefügt, die mit @JmsListener annotiert ist, die den Job erledigt und ich rufe es mit jmsTemplate.convertAndSend().

Aber wenn der findAll() Teil meiner Behandlung funktioniert perfekt, sobald ich Daten versuchen zuzugreifen (einfach zum Beispiel der Anzeige) mit der findAll() Methode abgerufen Ich LazyLoadingException auf meinen faulen Sammlungen gegenüber, sagte, dass ich nicht haben Hibernate-Sitzung Hier org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ..., could not initialize proxy - no Session

ist ein Ausschnitt aus meinem Code, ob das hilft:

public void myMethod(int batchSize) { 
    // Send a JMS message with a POJO 
    LOGGER.trace("Calling JMS method..."); 
    final JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); 
    jmsTemplate.convertAndSend("runJob", batchSize); 
} 

@JmsListener(destination = "runJob") 
private void runJob(final int batchSize) { 
    LOGGER.debug("Calling runJob with batchSize {}", batchSize); 
    List<MyEntity> myEntities = myRepository.findAll(); 
    LOGGER.debug("{} entities retrieved from the DB", myEntities.size()); // Prints the actual number of entities in my DB 
    for(Entity entity : entities){ 
     LOGGER.debug("Entity name {}", entity.getName()); // Prints entity name 
     LOGGER.debug("Entity first collection's value {}", entity.getMyList().get(0).toString()); // org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ..., could not initialize proxy - no Session 
    } 
} 

// ----------------------- 
// Full code of my repository -> The implementation is generated by spring-data http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation 
public interface MyRepository extends org.springframework.data.jpa.repository.JpaRepository<MyEntity, Long>{} 

Ich möchte nur wissen, wie meine Session meiner Jms Methode angebracht zu halten.

Cheers, Olivier

+2

Beschreiben Sie nicht Ihren Code und Ihre Ausnahme. Veröffentlichen Sie sie. –

+0

@JBNizet hat gerade ein Code-Snippet hinzugefügt. Übrigens wurde die Ausnahme in meinem ursprünglichen Post (LazyLoadingException auf meinen faulen Sammlungen) aufgelistet und der Code (Anzeigedaten) war auch da. Ich könnte mich aber auf das konzentrieren, was wirklich wichtig ist: das Problem und nicht reiner Code. Wie auch immer, hier ist es. – Olivier

Antwort

1

Ihre JmsListener Methode asynchron verarbeitet wird (das ist der springende Punkt, warum Sie das tun) so auf einem anderen Thread es läuft. Wenn es in einem anderen Thread ausgeführt wird, können Sie nicht dieselbe Transaktion verwenden.

Sie können jedoch eine neue Transaktion starten, wenn die JMS-Nachricht verarbeitet wird, aber Sie müssen erkennen, was das konkret bedeutet. Hinzufügen @Transactional auf runJob sollte es tun. Da es jetzt asynchron ist, müssen Sie dies in der Antwort berücksichtigen. Welchen HTTP-Statuscode werden Sie zurückgeben? Zum Beispiel kann etwas im Hintergrund fehlschlagen.

+0

danke für die antwort. Ich stimme zu 100% mit Ihnen überein, was das asynchrone Ziel betrifft. Natürlich versuche ich nicht, 'runJob' und' myMethod' in der gleichen Transaktion laufen zu lassen. Ich will nur 'runJob' nicht die Hibernate-Sitzung nach dem Aufruf von 'myRepository.findAll()' zu schließen. Ich habe vergessen, es zu erwähnen, aber ja, ich habe versucht, 'runJob'' @ Transactional' zu machen, habe aber keinen Erfolg. Wie du, ich würde es doch tun ... Und ich kann nicht verstehen, wie eine Methode "@ Transactional" sein kann, wenn sie ihre "Session" beim Laufen beendet ... Übrigens, ich habe so wenig Code mehr Man kann wissen, was die JMS-Methode bereits getan hat. – Olivier

+0

Ihre Methode ist privat, sie muss öffentlich sein, damit sie für Transaktionszwecke proxisiert werden kann. Ich bin eigentlich überrascht private Arbeiten überhaupt für '@ JmsListener' –

+0

tut mir leid, aber es löst das Problem nicht. Ich war mir sicher, dass es aber ... Ich stehe immer noch genau vor dem gleichen Problem, während ich alle meine Methoden öffentlich gemacht habe. – Olivier

Verwandte Themen