LINUX.ORG.RU

Scala, anorm и sql relations

 , ,


0

2

Привет всем!

Бывалые скалисты, подскажите как реализовываются связи many-to-many при использовании anorm.

Есть три таблицы: users, permissions и user_permissions. user относится к permissions как многие ко многим.

Есть отдельные парсеры для маппинга данных в объекты User и Permission. Вопрос, как реализовать anorm-парсер для объекта UserWithPermissions?

Пока имею конструкцию следующего вида.

case class UserWithPermissions(
  id: Int,
  username: String,
  email: String,
  uid: Option[String],
  password: String,
  first_name: Option[String],
  last_name: Option[String],
  avatar: Option[String],
  created: DateTime = DateTime.now,
  last_visited: Option[DateTime],
  is_activated: Boolean = false,
  is_admin: Boolean = false,
  permissions: List[Permission]
)

trait UserWithPermissionsSerialize {
  val writes = {
    get[Int]("id") ~
    get[String]("username") ~
    get[String]("email") ~
    get[Option[String]]("uid") ~
    get[String]("password") ~
    get[Option[String]]("first_name") ~
    get[Option[String]]("last_name") ~
    get[Option[String]]("avatar") ~
    get[DateTime]("created") ~
    get[Option[DateTime]]("last_visited") ~
    get[Boolean]("is_activated") ~
    get[Boolean]("is_admin") ~
    get[List[Permission]]("permissions") map {
      case id ~ username ~ email ~ uid ~ password ~ first_name ~ last_name ~ avatar ~ created ~ last_visited ~ is_activated ~ is_admin ~ permissions => UserWithPermissions(
        id,
        username,
        email,
        uid,
        password,
        first_name,
        last_name,
        avatar,
        created,
        last_visited,
        is_activated,
        is_admin,
        permissions
      )
    }
  }
}

object UserWithPermissions extends UserWithPermissionsSerialize

Но такая конструкция не работает. Я так понимаю, надо как-то подставить парсер для permissions в парсер UserWithPermission. Но как - не знаю... Имел ли кто-нибудь аналогичный опыт работы с anorm и межобъектными связями?



Последнее исправление: djnoob (всего исправлений: 1)

На уровне DAO, вроде все просто. А вот на уровне моделей и маппинга - темный лес.

djnoob
() автор топика
Ответ на: комментарий от djnoob

Т.е. понтно, да, что Permission - это другой case-class со свои парсером:

case class Permission(
  id: Int,
  title: String,
  comment: String
)

trait PermissionSerialize {
  val writes = {
    get[Int]("id") ~
    get[String]("title") ~
    get[String]("comment") map {
      case id ~ title ~ comment => Permission(id, title, comment)
    }
  }
}

object Permission extends PermissionSerialize 

djnoob
() автор топика

Доку почитать на playframwwork.com не судьба?

1) Для простого маппинга сто лет уже есть anorm.Macro и нафиг руками не надо писать эти get[Int](«id») ~ get[String](«username») ...

2) Парсеры точно так-же комбинируются тильдой ~

На скорую руку твой пример я бы сделал как-то так:


import java.sql.Connection
import anorm._

case class Permission(id: Long, title: String, content: String)

object Permission {
  val parser = anorm.Macro.namedParser[Permission]
}

case class User(id: Long, username: String)

object User {
  val parser = anorm.Macro.namedParser[User]
}


case class UserPermissions(user: User, permissions: List[Permission])

object UserPermissions {
  def find(userId: Long)(implicit conn : Connection)
    SQL"""select 
            user.*, 
            permission.* 
          from user
          left join userPermission on user.id = userpermisson.userid
          left join permission on permission.id = userpermission.permissionid"""
      .as(User.parser ~ Permission.parser.? *)
      .groupBy(_._1)
      .map { case (user, withPermissions) =>
        val permissions = withPermissions.flatMap(_._2)
        UserPermissions(user, permissions)
      }
  }
}


anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.