2010-01-07 2 views
2

나는 grails : decks와 cards에서 many-to-many 관계를 갖는 2 개의 도메인 클래스를 가지고있다.grails : many-to-many 관계에 대한 hql 쿼리에서 join 테이블에 접근하기

셋업은 다음과 같습니다 : 나는 갑판을 삭제 한 후

class Deck { 
static hasMany = [cards: Card] 
} 

class Card { 
static hasMany = [decks: Deck] 
static belongsTo = Deck 
} 

가, 나 또한 더 이상 갑판에 속하는없는 카드를 모두 삭제합니다. 이 작업을 수행하는 가장 쉬운 방법은 다음과 같은 SQL과 같이 작성하는 것입니다 : 나는 테이블을 조인 때문에 SQL에 해결하는 HQL 쿼리를 작성하는 방법을 알아낼 수 없습니다, 그러나

delete from card where card.id not in(select card_id from deck_cards); 

을 deck_cards, 않습니다 해당 grails 도메인 클래스가 없습니다. HQL은 delete 문에서 조인을 사용할 수 없기 때문에 하위 쿼리를 사용하면 테이블을 참조 할 수 없기 때문에 mySQL이이 제한을 피하기 위해 불만을 제기하기 때문에 일반 조인을 사용하여이 명령문을 작성할 수 없습니다. 하위 쿼리의 "보낸 사람"섹션에서 삭제합니다.

최대 절전 모드 "delete-orphan"캐스케이드 옵션을 사용해 보았지만 그 카드가 다른 데크에도 속하더라도 데크가 삭제 될 때 모든 카드가 삭제됩니다. 나는 미쳐 가고 있습니다 - 이것은 단순한 작업처럼 보입니다.

편집 "데크"및 "카드"의 특정 사용에 대해 약간의 혼란이있는 것 같습니다. 이 응용 프로그램에서 "카드"는 플래시 카드이며 갑판에는 수만 개가있을 수 있습니다. 또한 사용자가 적합하다고 편집 할 수 있도록 데크를 복사해야하는 경우가 있습니다. 이 시나리오에서는 모든 카드를 복사하는 대신 새 데크가 이전 데크와 동일한 카드를 참조하며 카드가 변경된 경우에만 새로운 카드가 만들어집니다. 또한 groovy의 루프에서이 삭제 작업을 수행 할 수 있지만 위의 SQL을 사용하여 1 개가 아닌 수천 개의 SQL 삭제 명령문을 생성하므로 매우 느리고 자원 집약적입니다. HQL에서 조인 테이블의 속성에 액세스 할 수있는 방법이 있습니까?

답변

1

먼저, 엔티티의 요점이 표시되지 않습니다. 카드를 두 개 이상의 덱에 속하게하는 것은 비논리적입니다. 그리고 belongTohasMany을 모두 갖는 것은 비논리적입니다.

어쨌든, 삭제에는 HQL을 사용하지 마십시오. 당신이 실제로 OneToMany 필요한 경우

, session.remove(deck)를 사용하고 REMOVE 또는 ALLcardscascade을 설정합니다.

정말로 ManyToMany을 원할 경우 엔티티의 수표 을 수동으로 확인하십시오. 의사 코드 (이후 나는 grails 모르겠다) :

for (Card card : deck.cards} { 
    if (card.decks.size == 0) { 
     session.remove(card); 
    } 
} 
+0

데크와 카드가이 응용 프로그램에서 작동하는 방식에 대해 좀 더 구체적으로 설명 했어야합니다. 이것은 플래시 카드 응용 프로그램이며 "갑판"은 수만 장의 카드를 가질 수 있습니다. 또한 사용자가 자신의 버전을 만들 수 있도록 데크를 복제해야하는 경우도 있습니다. 이 경우 수만 장의 카드를 복사하는 대신 다른 카드에 카드를 추가하기 만하면됩니다. 따라서 다 대다 관계가 있습니다. 또한, grails에서, belongsTo를 갖는 것은 many to many가 여전히 정확합니다. 나는 매우 비효율적이기 때문에 groovy에서 각 카드를 수동으로 반복하고 싶지 않습니다. –

+0

같은 작은 숫자에 대한 효율성에 대해 걱정하지 마십시오. 또는 적어도 벤치 마크를 작성하고 시간을 확인하십시오. – Bozho

0

나는 기술적 인 측면에 답하고 있지만 모델에 도전하지 않을 것이다.

    덱이
  • 변화 : :이 또한 기능적으로


    :-) 당신에게 도움이 될 것입니다 희망, 당신의 두 객체가 같은 라이프 사이클이없는 나에게 보인다 그들은 카드로 작성, 수정 및 삭제됩니다.그렇지 않으면 코드를 사용하여 다시 만들 수 없으므로 확실히 데이터베이스에 저장해야합니다.

  • 카드는 일정합니다. : 모든 카드 세트는 처음부터 알려져 있으며 계속 유지됩니다. 데이터베이스에서 카드를 한 번 삭제하면 나중에 다른 사용자가 카드를 덱에 넣어야 할 때 같은 카드를 다시 만들어야하므로 모든 경우에 가능한 카드 목록을 제공하는 데이터 구조를 갖게됩니다 . 데이터베이스에 저장되지 않은 경우 다시 만들 수 있습니다.

모델에서 제공하는 카드에는 해당 카드가 들어있는 덱 세트가 있습니다. 그러나 그 정보는 덱 (변경)과 동일한 수명주기를 가지므로 은 갑판의 측면 인 (단방향 다 대다 관계)에서만 연결을 유지할 것을 제안합니다.

이제 카드는 항상 일정한 정보이므로 데이터베이스에 저장하지 않아도됩니다. 두 번째 테이블 (갑판 외에도)은 여전히 ​​있지만, 카드 테이블에는 카드에 대한 식별 정보 만 포함됩니다 (간단한 정수 1 - 52 또는 " 선택 ")하고 다른 필드 (이미지, 강도, 일부 포인트 등 ...)가 아닙니다. 최대 절전 모드에서


, 이러한 선택은 값 ( Hibernate reference 참조)의 컬렉션에 다 대다 관계를 켭니다.

값의 컬렉션을 사용하면 카드가 엔티티가 아니라 구성 요소가됩니다. 을 삭제할 필요없이 모든 것이 자동으로 최대 절전 모드로 처리됩니다.

+1

처음 게시물을 올렸을 때이를 명확히하지 못해 사과드립니다.하지만이 라이프 사이클이 올바르지 않습니다. 카드는 일정하지 않습니다. 카드는 갑판에서만 만들 수 있습니다. 한 갑판에서 다른 갑판으로 카드를 옮기는 유일한 방법은 갑판을 "복제"하는 것입니다.이 경우 카드는 두 갑판에 모두 소속됩니다. 유스 케이스를 명확히하기 위해 원본 게시물을 편집했습니다. –

관련 문제