2014-06-19 4 views
6

Grails 프로젝트를 1.3.7에서 2.4.0으로 업그레이드 한 후 새로운 grails 버전과 관련된 여러 문제를 수정 한 후에 어떤 객체에 대해서도 변경된 사항이 없을 것입니다. save(flush:true)이 호출 된 경우를 제외하고는 더 이상 지속되지 않습니다.플러시 모드가 자동에서 수동으로 변경되었습니다.

Grails 1.3.7에서 save()을 사용하여 도메인 인스턴스를 저장할 때의 기본 동작은 최대 절전 모드 flushMode =>FlushMode.AUTO으로 인해 변경 사항이 자동으로 지속된다는 것입니다. Grails 2.4.0에서 이것은 더 이상 사실이 아닙니다. 컨트롤러 조치 또는 서비스 클래스 내의 최대 절전 모드 세션의 기본 flushMode는 FlushMode.MANUAL입니다.

FlushMode.AUTO 값을 가지고 있고 값이 FlushMode.MANUAL 인 컨트롤러 동작에서 부트 스트랩에서 sessionFactory.currentSession.flushMode을 검색 할 때 상황이 더 이상합니다. 이것은 새로운 grails 앱을 만들고 println "flushMode = $sessionFactory.currentSession.flushMode"을 부트 스트랩과 컨트롤러 액션 (예 : index())에 넣음으로써 검증 할 수 있습니다.

나는 지난 2 일 동안 모든 종류의 포럼을 검색해 왔으며 Grails 2.4.0 (또는 이전 버전에서도)이 변경된 이유를 알지 못했습니다. 난 단지 FlushMode.MANUAL을 가질 위험성이 있다고 말하는 주석을 발견했다. 다른 일부가 수정 된 후에 db를 질의 할 때 부실한 객체를 실행할 수 있기 때문이다. 설정에서

grails.gorm.autoFlush = true
  • 당신이 플러시를 강제 할 수 있습니다 :

    내가 알고있는 모든 진실은 Hibernate3은과 hibernate4 기본 flushMode에서

  • FlushMode.AUTO
  • 입니다) (저장의 flushMode을 설정할 수 없습니다 Config.groovy 또는 DataSource.groovy에 있습니다. 나는이 모든 것을 시도했지만 아무 일도하지 않았다 : hibernate.flush.mode = 'auto' hibernate.flushMode = 'auto' hibernate.session.flush.mode = 'auto' hibernate.session.flushMode = 'auto' dataSource.hibernate.flush.mode = 'auto' dataSource.hibernate.flushMode = 'auto' dataSource.hibernate.session.flush.mode = 'auto' dataSource.hibernate.session.flushMode = 'auto' dataSource.flush.mode = 'auto' dataSource.flushMode = 'auto' dataSource.session.flush.mode = 'auto' dataSource.session.flushMode = 'auto'

누군가이 작은 빛을 던질 수 있습니까?

실제로 Grails 2.4.0에서 FlushMode.MANUAL이 현재 원하는 기본값인지 알고 싶습니다.

코멘트와 함께 무엇
  • 피터 Ledbrook에 의해 GRAILS-7180
  • 가장 좋은 방법 무엇 "... 제안은 우리가 완전히 자동 세척 모드를 해제하는 것이 ... 아니다"

    그리고 만약 그렇다면

    특히 새 인스턴스를 작성하고 쿼리를 작성하는 모든 도메인 객체가 복잡한 조작을 수행 할 때 오래된 객체의 문제에 부딪치지 않습니다.

정말 감사합니다 - 앤디


Graemes 응답 및 자신의 의견을 읽고되면, 더 나은 내가 고민하고 무엇을 명확히하기 위해 노력하고 그 동작을 보여 다음과 같은 단순화 된 도메인 컨트롤러 클래스를 추가 :

도메인 클래스 메시지 :

class Msg { 

    String text 

    static constraints = { 
     text nullable:true 
    } 
} 
,536,913,632 10

과 MSG 컨트롤러 :

class MsgController { 
    def sessionFactory 

    def index = { 
     def out = ["*** flushMode when in controller/index = \ 
        $sessionFactory.currentSession.flushMode"] 
     Msg.list().each { out << "$it.id: text=$it.text" } 
     render out.join('<br>') 
    } 

    // this save does persist the new msg object, 
    // even if flushMode = MANUAL 
    def save1 = { 
     def out = ["*** flushMode when in controller/save = \ 
        $sessionFactory.currentSession.flushMode"] 
     def msg = new Msg(text:'hallo') 
     if (!msg.save()) { 
      out << "msg has errors! " + msg.errors 
     } 
     out << "msg $msg.id created with text = $msg.text" 
     render out.join('<br>') 
    } 

    // this save does NOT persist the new msg object, even if its valid 
    // (difference is calling hasErrors() 
    def save2 = { 
     def out = ["*** flushMode when in controller/save = \ 
        $sessionFactory.currentSession.flushMode"] 
     def msg = new Msg(text:'hallo') 
     if (msg.hasErrors() && !msg.save()) { 
      out << "msg has errors! " + msg.errors 
     } 
     out << "msg $msg.id created with text = $msg.text" 
     render out.join('<br>') 
    } 
} 


그래서 http://localhost/appname/msg/save1 출력을 호출은 다음과 같습니다

여기
*** flushMode when in controller/save1 = MANUAL 
msg 1 created with text = hallo 

나는 그것을 얻지 않는다, 최대 절전 모드 개체를 계속하는 이유도 그대 flushMode는 MANUAL입니다.

그리고 http://localhost/appname/msg/save2를 호출 할 때 출력은 다음과 같습니다 최대 절전 모드가 플러시를 발행하지 않기 때문에

*** flushMode when in controller/save2 = MANUAL 
msg null created with text = hallo 

목적은 따라서 SQL "업데이트 ..."명령을 호출 결코 지속되지 않습니다.

하지만 이제는 flushMode가 문제가되는 것뿐만 아니라 hasErrors()가 호출되는 것처럼 보일 수도 있습니다. 나는 더 이상 당황 스럽다 ...

이 예제를 Grails 1.3.7에서 실행하면 두 save 액션 (save1과 save2)은 새로 생성 된 msg 객체를 지속시킨다!

답변

8

Grails는 유효성 검사 중에 플러시 모드를 수동으로 설정하여 유효성 검사 중에 변경 사항이 플러시되지 않도록합니다 (기존 데이터를 쿼리하는 사용자 정의 유효성 검사기가있을 수 있으므로 매우 일반적 일 수 있음).

는 유효성 검사 오류가있는 경우 https://github.com/grails/grails-data-mapping/blob/master/grails-datastore-gorm-hibernate4/src/main/groovy/org/codehaus/groovy/grails/orm/hibernate/validation/HibernateDomainClassValidator.java#L60

그것이 AUTO로 다시 세척 모드를 설정하지 않습니다를 참조하십시오. 이는 유효하지 않은 오브젝트가 지속되지 않도록하기위한 것입니다.

보고있는 내용은 유효성 검사 오류가 발생했을 가능성이 있으며 플러시를 강제 할 수는 있지만 권장하지 않습니다.

+0

설명해 주셔서 감사합니다. 그게 말이 되네. 하지만 도메인 객체가 저장되지 않더라도 (전혀 사용되지 않아도) Grails가 컨트롤러 작업에서 MANUAL로 전환하는 이유는 무엇입니까? 나는 그것을 확인하기 위해 단지 하나의 컨트롤러와 도메인 클래스가없는 작은 Grails 애플리케이션을 작성했다. 컨트롤러 인덱스 액션에서 나는 단지 1 LOC'println "을 넣는다. flushMode = $ sessionFactory.currentSession.flushMode" –

+0

읽기 연산을 위해서 Grails는 읽기 전용 트랜잭션을 사용한다. 읽기 전용 트랜잭션은 플러시 모드 (MANUAL)를 사용합니다. 읽기 작업이 읽기 전용 트랜잭션을 사용하는 이유는 Hibernate가 읽기 전용 객체를 더티 검사 할 필요가 없으므로 성능을 향상시키기 때문입니다. 이것은 당신이보고있는 것일 수 있습니다. –

+0

업데이트 된 도메인 및 컨트롤러 예제로 원래 질문보기 –