2014-09-16 1 views
0

주어진 도메인 개체에 대한 작업을 수행하는 grails 서비스가 있습니다. 이 작업은 실패 할 수 있으며, 그럴 경우 해당 작업의 트랜잭션을 롤백해야합니다.요청 당 여러 트랜잭션에 대한 LazyInitializationException

또한이 도메인 클래스의 모든 인스턴스에 대해 루프를 실행하여 각 도메인에서 서비스를 호출하는 컨트롤러가 있습니다. 주어진 객체에 대한 서비스 연산이 실패하면, 나는 나머지 독립적 인 트랜젝션으로 나머지 도메인 객체들을 계속 처리하기를 원한다.

그냥 명확히하기 위해 집안의 모든 객실 (아래 도메인 클래스 참조)은 단일 거래 내에서 처리해야하지만 집당 별도의 거래가 필요합니다.

이 방법이 있습니까? 아래는 내가 시도한 것입니다. 그러나 그 중 하나의 작업이 실패한 후 후속 개체를 처리하려고 할 때 아래 예외가 계속 발생합니다. 아마도 트랜잭션이 롤백 될 때 Hibernate 세션이 닫히고있을 수 있습니까?

(참고 :. 우리의 실제 도메인 클래스가 실제로 여러 hasMany의 관계를 포함하는 열망로드로 전환하는 것은, 아마 나를 위해 옵션을 선택하지 않습니다)

예외 :

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.blah.House.rooms, no session or session was closed 

코드 :

class DataService { 
    static transactional = true 

    def processStuff(House house){ 
     house.rooms.each{ 
      if(someCondition){ 
       throw new RuntimeException('failed') // will cause txn to roll back 
      } 
     } 
    } 
} 

class DataController { 

    def dataService 

    def doSomething(){ 
     def houses = House.findAll() 
     houses.each{ house -> 
      dataService.processStuff(house) 
     } 
     render(view:'someView') 
    } 
} 

class House { 
    def hasMany = [rooms: Room] 
} 
class Room { 
} 
+0

'processStuff' 메소드의 내부를'Room.withTransaction {/ * your code * /}'로 감쌀 경우 어떻게됩니까? – Casey

+0

서비스에서 '트랜잭션'을 false로 설정한다고 가정합니다. 결과는 완전히 동일합니다. – GreenGiant

답변

0

근본적인 문제는 트랜잭션이 롤백 될 때 Hibernate 세션이 지워지므로 (모든 지연로드 된 콜렉션이 유효하지 않음을 의미한다). 이 문제는 Grails docs의 (해결 방법과 함께) 문서화되어 있습니다.

필자의 경우 가장 좋은 해결책은 각 트랜잭션이 시작될 때 부모 개체를 다시로드하는 것입니다. 이것은 lazy-loading 컬렉션을 다시 초기화 할 것입니다.