콘텐츠로 이동

2023 04 17

2023-04-17

Slick Join

  • 예시 테이블
    case class Person(id: Int, name: String, age: Int)
    
    class PersonTable(tag: Tag) extends Table[Person](tag, "person") {
        def id = column[Int]("id", O.PrimaryKey)
        def name = column[String]("name")
        def age = column[Int]("age")
    
        def * = (id, name, age) <> (Person.tupled, Person.unapply)
    }
    
    case class Address(id: Int, street: String, city: String, state: String, zip: String, personId: Int)
    
    class AddressTable(tag: Tag) extends Table[Address](tag, "address") {
        def id = column[Int]("id", O.PrimaryKey)
        def street = column[String]("street")
        def city = column[String]("city")
        def state = column[String]("state")
        def zip = column[String]("zip")
        def personId = column[Int]("person_id")
    
        def person = foreignKey("person_fk", personId, TableQuery[PersonTable])(_.id)
    
        def * = (id, street, city, state, zip, personId) <> (Address.tupled, Address.unapply)
    }
    
  • Join 해보자
    val query = for {
        (p, a) <- TableQuery[PersonTable].join(TableQuery[AddressTable]).on(_id === _.personId)
    } yield (p.name, a.street, a.city)
    
    val result = db.run(query.result)
    
  • 왜 for-comprehension을 쓰는거지?
    • concise and readable 하기 위해서 임
    • (p, a) <- TableQuery[PersonTable].join(TableQuery[AddressTable]).on(_id === _.personId)
      • 여기서...
        • p = PersonTable
        • a = AddressTable
      • yield...
        • 열심히 조인해서 어떤 튜플 가져올지?!
          • (p.name, a.street, a.city)
      • join 해서 결국 가져올 칼럼 깔끔하게 쓸 수 있음
  • Pagination은?

    • 단일 테이블에 대해서 페이지네이션
      val pageNumber = 1
      val pageSize = 10
      val offset = (pageNumber - 1) * pageSize
      
      val query = TableQuery[PersonTable].sortBy(_.id).drop(offset).take(pageSize)
      val result = db.run(query.result)
      
    • join 하고 난 뒤 페이지네이션
      val pageNumber = 1
      val pageSize = 10
      val offset = (pageNumber - 1) * pageSize
      
      val query = for {
        (p, a) <- TableQuery[PersonTable].join(TableQuery[AddressTable]).on(_.id === _.personId)
                .sortBy(_._1.id)  // 여기서 _1 는 튜플의 첫 원소를 말함. 여기서는 p를 뜻한다
                .drop(offset)
                .take(pageSize)
      } yield (p.name, a.street, a.city)
      
      val result = db.run(query.result)