Ответы пользователя по тегу Базы данных
  • Как происходит связь моделей с бд в java/scala приложениях?

    @kondaurov
    Full stack developer
    Развенлул приложение на PlayFramework2 (стандартный шаблон typesafe). С контроллерами, конфигами, вьюхами все понятно. А вот с моделями затык.


    Я не совсем понимаю в чем у вас затык. Не знаете как реализовать получение строк из таблицы? Все очень просто!

    https://www.playframework.com/documentation/2.3.6/... вам в помощь

    В scala есть такая крутая штука как case class. Описание объектов этих кейс классов immutable, изменить можно только лишь скопировав объект с измененным полем (полями).

    case class User(id: Option[Long] = None, name: String, password: String)
    val a = User("John", "super")
    val b = User.copy(name = "John2", password = "bla")


    В принципе можно мапить строки таблицы и в обычный класс с приватными полями но как я думаю создатели языка именно для этих целей уже сделали эти кейс классы.

    Почему immutable важно? Когда у меня есть коллекция кейс классов я знаю что никакие поля не изменятся в течение всего периода времени существования объектов этих кейс классов

    Кейс классы знать нужно и уметь делать нужные, на все возможные случаи! Именно поэтому это case class а не forever_stable_structure class
    Может показать что это не по теме но они используются везде, это главный друг scala программиста использующего play framework (да и не только, проекты на scala вообщем)

    В пакете у меня несколько кейс классов для одной сущности. Нету времени на примеры

    Получить запись пользователя из таблицы user по id можно так:

    import anorm._
    
    def getUserById(userId: Long): Option[User] = DB.withConnection { implicit r =>
    
    SQL("SELECT * FROM users WHERE user_id = {userId}").on(
     'userId -> 
    ).map(r => User(
     "id" -> r[Option[Long]]("id"),
     "name" -> r[String]("name"),
     "password" -> r[String]("password")
    )).singleOpt()
    
    }


    Или, во избежание дублирования кода маппинга полей таблицы в поля кейс класс, можно запихнуть этот код в объект компаньон кейс класса

    package models.user.User
    
    object User {
    
     def map(r: anorm.Row): User = User(
     "id" -> r[Option[Long]]("id"),
     "name" -> r[String]("name"),
     "password" -> r[String]("password")
    )
    
    }
    
    case class User(id: Option[Long], name: String, password: String)


    Потом создаем объект который я называю DAO. Он делает sql запрос и указывает какой функцией смапить строки отданные базой данных

    //###########

    package models.user.UsersDAO
    
    import play.api.db.DB
    import anorm._
    
    def getUserById(id: Long): Option[User] = DB.withConnection { implicit r =>
    
    SQL("SELECT * FROM users WHERE user_id = {userId}").on(
     'userId' -> id
    ).map(User.map).singleOpt()
    
    }


    Все очень просто и никаких затыков нету если ВНИМАТЕЛЬНО читать и стараться разобраться в сути а не делать так:
    Я разорался с синтаксисом Scala (с Java был поверхностно знаком)


    PS: Забыл упомянуть про Slick. Это такая штука которая избавляет от написания функций map(r: anorm.Row) и написания чистого SQL кода. В результате получается typesafe way в работе с получением данных от базы данных. Компилятор сразу компилирует мета код в чистый SQL и выплюнет ошибку если поле не правильно задано или тип не совпадает, тп. Это крутая вещь и с ней СТОИТ разобраться но сначала разберитесь с анормом, мне его пока хватает! Читайте мануалы по анорму, там все круто описано и я даже сам не знаю зачем все это написал когда сам во всем разобрался тем путем
    Ответ написан
    Комментировать