2016-12-05 1 views
0

UserDao에서 나는 사용자에게 주어진 모든 보안 역할을 부여받는 메서드를 정의하려고합니다.Slick 3.1.x 다 대다 조인을 구현하는 방법은 무엇입니까?

User(PK id) 
SecurityRole(PK id) 
UserSecurityRole(
    userId FK to User(id), 
    securityRoleId FK to SecurityRole(id) 
) 

따라서 나는이처럼 내 getRoles 함수를 정의하려고 :

def getRoles(user: UserRow) : Future[List[SecurityRoleRow]] = { 
    val action = for { 
    role <- SecurityRole join UserSecurityRole on (_.id === _.securityRoleId) 
      join User on (_.userId === _.id) 
    } yield role 
    db.run(action) 
} 

또는이 같은 :

이 여기에 다 대다 관계, 의사 데이터베이스 설계 ( here is the actual Tables.scala full generated implementation)입니다
def getRoles(user: UserRow) : Future[List[SecurityRoleRow]] = { 
    val action = for { 
    role <- SecurityRole join (UserSecurityRole join User on (_.userId === _.id)) on (_.id === _.securityRoleId) 
    } yield role 
    db.run(action) 
} 

두 경우 모두 출력이 Role이어야하고 따라서 시작하는 컴파일러 오류 can not resolve symbol _.userId가 표시됩니다. 두 대안 모두 내가 SecurityRole을 가지고 있기 때문에 그것이 내가 필요로하기 때문입니다. 내 인상은 첫 번째 조인 후에 일부 열이 지워지거나? 그것 뿐이다

SELECT t1.* 
FROM SecurityRole t1, 
    UserSecurityRole t2, 
    User t3 
WHERE t1.id = t2.securityRoleId 
    AND t3.id = t2.userId 

:

는 SQL에서이 같이 간단 할 것입니다. 내 UserDao으로이 SQL을 slickifying 원한다면 그럼 내가 할 수있는 :

def getRoles(user: UserRow) : Future[List[SecurityRoleRow]] = { 
    val action = sql"""SELECT t1.* " + 
        "FROM SecurityRole t1, " + 
         "UserSecurityRole t2, " + 
        "WHERE t1.id = t2.securityRoleId " + 
         "AND ${user.id} = t2.userId""".as[SecurityRoleRow] 
    db.run(action) 
} 

답변

2

당신은 기본적으로 오른쪽 (물론, 가지, 그들은 전멸되지 않고 오히려 튜플이 연장됩니다)입니다. 이 대신 : 각각의 새로운 가입

def getRoles(user: UserRow) : Future[List[SecurityRoleRow]] = { 
    val action = (for { 
    role <- SecurityRole join UserSecurityRole on (_.id === _.securityRoleId) 
      join User on (_._2.userId === _.id) // here is the change!! 
    } yield role).result 
    db.run(action) 
} 

새로운 중첩 된 튜플을 추가

def getRoles(user: UserRow) : Future[List[SecurityRoleRow]] = { 
    val action = for { 
    role <- SecurityRole join UserSecurityRole on (_.id === _.securityRoleId) 
      join User on (_.userId === _.id) 
    } yield role 
    db.run(action) 
} 

은 사용한다

(BTW 당신은 ​​내가 생각에 대한 result 전화를 잊었). 내 슬라이드에서이 슬라이드를 봅니다. (이 튜플은 패턴 매칭으로 각 유형을 분해하지만 모두 동일합니다) : http://slides.com/pdolega/slick-101#/75 (특히 - 외래 키를 사용하여 다음 단계를 살펴보십시오.) 그것은 완벽한 해결책이 될 것입니다).

편집 :

에도 외부 키 (난 당신이해야한다고 생각하는) 당신은 모든 튜플 중첩 방지하는 모나드 형태로 버전을 변경할 수 있습니다 정의하지 않고 : 기본적으로 조반니 - 아 수아 @

val action = (for { 
    role <- SecurityRole 
    userRole <- UserSecurityRole if role.id === userRole.securityRoleId 
    user <- User if userRole.userId === user.id 
} yield role).result 

db.run(action) 
+1

I을 프리젠 테이션 및 관련 저장소를 살펴 보도록 조언합니다. 이것은 Slick 3.x의 기초에 대한 일종의 빠른 소개를 의미합니다. 리소스 섹션에는 Dave Gurnell (https://vimeo.com/148074461)이 운영하는 매우 훌륭한 워크샵 기록에 대한 링크가 있습니다. –

+0

철저한 답변 주셔서 감사합니다! 순수한 매끄러운 SQL 버전을 사용하여 성능이 어떻게 비교됩니까? 나는 생성 된 SQL을 얻는 방법을 발견 할 것이다. 많은 감사합니다! –

+1

내가 링크 된 슬라이드에 SQL을 생성했습니다. 또한 생성 된 것을 쉽게보기 위해서'logback.xml'에이 로거 세트를 추가하기 만하면됩니다 : ' "DEBUG"/>' –

관련 문제