Grails 2.3.7에서 부모/자식 관계와의 데이터 바인딩을 사용하고 있으며 삭제하는 데 문제가 있습니다. 양식에 많은 선택적 자식이 있으며 데이터베이스를 깔끔하게 유지하기 위해 공백 (null) 값을 제거하고 싶습니다. 나는 항목을 필터링하기 위해 removeAll을 사용하는 것이 좋지만 제거 또는 removeAll을 사용할 수 없다는 좋은 기사를 발견했습니다! 예를 들어Groovy removeAll 클로저가 Set의 객체를 제거하지 않음
...
나는 PersistentSet을 읽은def update(Parent parent) {
parent.children.getClass() // returns org.hibernate.collection.PersistentSet
parent.children.size() // returns 10
parent.children.findAll{ it.value == null }.size() // returns 5
parent.children.removeAll{ it.value == null } // returns TRUE
parent.children.size() // Still returns 10!!!
}
내가했던 수동으로 구현되는 equals()와 hashCode()에 대한 까다로운입니다 (상위 10 명 어린이 (5)는 비어있다) 모든 도메인 클래스에서. 콜렉션이 변경되었음을 나타내는 removeAll이 true를 리턴 할 수있는 방법은 무엇입니까? 나는 2 일 동안 이것에 붙어 있었고, 어떤 조언도 감사 할 것이다. 감사.
업데이트 : 아동의 해시 코드 실험 봤는데 그 범인 것으로 보인다
. 만약 id (bad practice)를 기반으로 베어 본 해시 코드를 만들면 removeAll이 작동하지만 값을 포함 시키면 다시 작동하지 않습니다. 예를 들어 ...
// Sample 1: Works with removeAll
int hashCode() {
int hash1 = id.hashCode()
return hash1
}
// Sample 2: Doesn't work with removeAll
int hashCode() {
int hash1 = id.hashCode()
int hash2 = value == null ? 0 : value.hashCode()
return hash1 + hash2
}
// Sample Domain classes (thanks Burt)
class Parent {
static hasMany = [children: Child]
}
class Child {
String name
String value
static constraints = {
value nullable: true
}
}
이 동작은 데이터를 업데이트하는 데이터가 더럽혀 져서 설명됩니다. (예 : child.value.isDirty() == true) 다음은이를 이해하는 방법입니다.
First Grails 데이터 바인딩은 부모와 자식을 가져오고 각 자식의 해시 코드가 계산됩니다. 다음으로, 변경된 경우 child.value를 더티하게 만들지 만 Set의 해시 코드는 변경되지 않은 상태로 유지되는 데이터 업데이트가 적용됩니다. removeAll이 일치하는 것을 발견하면 더티 데이터로 hashCode를 작성하지만 해시 코드는 Set에서 찾을 수 없으므로 제거 할 수 없습니다. 본질적으로 removeAll은 모든 hashCode 변수가 깨끗한 경우에만 작동합니다.
데이터를 제거하려면 데이터를 깨끗하게해야합니다. 한 가지 해결책은 두 번 저장하는 것입니다. 이처럼 ...
// Parent Controller
def update(Parent parent) {
parent.children.removeAll{ it.value == null } // Removes CLEAN children with no value
parent.save(flush:true)
parent.refresh() // parent.children is now clean
parent.children.removeAll{ it.value == null } // Removes (formerly dirty) children
parent.save(flush:true) // Success!
}
이것은 이상적이지만 작동합니다. 먼저 데이터베이스에 null 값을 허용해야합니다. 단 몇 초만 존재하지만 그 값은 필요하지 않습니다. 그리고 두 번째로 두 가지 절약을하는 것이 비효율적입니다. 확실하게 더 좋은 방법이 있어야만합니까? 더 contains
전화 또는 hashCode
값을 사용하고 잠재적으로 실제 데이터를 놓칠 비슷한 일이없는 -
removeAll 전후에 자녀를 인쇄하면 무엇을 얻게됩니까? – injecteer
제발, 당신의'''부모''클래스를 게시하십시오 – Victor
시도해보십시오 :'parent.children.findAll {it.value == null} *. removeFromParent (parent)' –