2011-02-14 3 views
2

내 응용 프로그램에서 xml 파일을 구문 분석 중이며이를 설계하는 방법에 대해 조금 고심하고 있습니다.Grails 서비스 클래스의 트랜잭션 동작 호출 연결

우리는 xml 스키마의 "불완전한"트리를 업로드 할 수 있습니다. 즉, 트리가 잘 형성되어있는 한 루트 노드의 하위 하위 노드가 될 수 있습니다. 대부분의 노드는 일부 텍스트 (속성) 만 포함하는 자식 노드를 가지고 있지만이 중 작은 xml 구조체 예제에는 포함되지 않았습니다.

<root> 
    <childFoo> 
     <childBar> 
     </childBar> 
    </childFoo> 
</root> 

이러한 노드 중 하나는 허용됩니다. 이제 다양한 노드를 구문 분석 할 수있는 메서드가있는 XmlInputService를 디자인했습니다. 그리고 난 컨트롤러에서 어떤 종류의 노드인지를 감지하고 이에 따라 서비스 메소드에 넘깁니다.

내 코드를 건조하고 멋지게 유지하려면 상위 메소드에서 메소드를 다시 사용하십시오. Root 유형의 문서를 서비스에 전달하면 루트에 직접있는 루트의 모든 필드를 구문 분석하고 자식 노드 (내 도메인 클래스 구조의 자식을 나타냄)를 적절한 구문 분석 메소드로 전달합니다. 서비스.

이제 제약 조건 위반이 포함 된 XML (예 : 고유하지 않은 이름의 요소 등)을 사용자가 업로드하면 분명히이를 롤백하고 싶습니다.

내가 parseRoot()를 호출하고 아래쪽으로 가서 parseChildFoo()를 호출한다고 가정합니다.

거기에있는 모든 Bar 자식에 대해 parseChildBar()가 호출됩니다. Bar 자식 중 하나가 제약 조건 등으로 인해 유효성을 검사 할 수없는 경우, 분명히 트랜잭션의 롤백을 parseFoo()까지 모두 계단식으로 처리하려고합니다.

어떻게하면 좋을까요?

+0

내가이 게시물을 만든 후 시간 일 주위에 나는 기본 스프링 서비스가 하나의 트랜잭션 중첩 된 서비스 요청을 치료하는 것을 발견, 그래서 나는 좀 내 자신의 문제를 대답했다.미래에이 대답을 찾는 사람들은 failOnError : true를 가진 save()를 속성으로 호출하면 ValidationException (RunTime의 하위 클래스)을 던져서 트랜잭션을 종료합니다. 두 가지 repliers에게 감사합니다. –

답변

1

파싱을 처리하는 메소드가있는 grails 서비스를 사용하는 경우 서비스에서 java.lang.RuntimeException을 확장하는 예외를 throw하여 사용자가 XML을 수정해야한다는 사실을 사용자에게 알릴 수 있도록해야합니다 . 컨트롤러는 예외를 잡아 사용자에게 의미있는 오류 메시지를 제공합니다.

데이터베이스 수정의 롤백은 서비스 메소드에서 런타임 예외가 발생할 때마다 Grails/Spring에 의해 자동으로 수행됩니다.

Victor의 대답에 대해 설명하는 방식의 이점은 실패시 트랜잭션을 롤백 할 수 있도록 코드를 작성할 필요가 없다는 것입니다. Grails가 당신을 위해 그것을 할 것입니다. 서비스 방법 내에서 withTransaction 클로저를 사용하는 IMO는 의미가 없습니다.

More info here

+0

사실 나는 마지막 문장에서 그렇게 말했습니다. 'withTransaction'은 서비스 자체가 트랜잭션 적이 아닌 경우 의미가 있습니다. –

+0

하지만 답변은 너무 많은 시간을 이야기하기 때문에 withTransaction의 사용을 권장합니다. 그것이 내 대답의 주된 이유입니다. –

1

도메인 개체에 대한 유효성 검사 유효성 검사 제약 조건을 만듭니다.

save()가 제약 조건을 위반하면 예외를 throw하고 최상위 구문 분석 수준에서 catch 한 다음 전체 트랜잭션을 롤백합니다. 처럼 :

meServiceMethod() { 
    ... 
    FooDomainClass.withTransaction { status -> 
     try { 
      parseRoot(xml) 
     } 
     catch (FooBarParentException e) { 
      status.setRollbackOnly() 
      // whatever error diagnostics 
     } 
    } 
    ... 
} 

아니면 단순히 예외가 컨트롤러에 서비스 방법에서 비행하도록 할 수 있습니다 - 서비스 방법은 기본적으로 트랜잭션입니다.