Вопрос: Как происходит связь моделей с бд в java/scala приложениях?

Лучший ответ: В мире Java есть много способов организации связи с БД и связи моделей с БД в частности. Есть стандарт - JPA. В мире spring есть слой совместимости с JPA, есть и иные решения. В Scala можно использовать и вышеупомянутые решения, и свои (тут уже зависит от используемого фреймворка).
Опишу, как это устроено в JPA.
Сперва ты описываешь связь всего приложения с БД в файле persistence.xml. В нём ты описываешь persistence-unit'ы - единицы персистентности, связь моделей с БД. Грубо говоря, можно использовать как локальные ресурсы (RESOURCE_LOCAL - связь происходит не через сервер приложений, а сторонними усилиями, связь описывается в xml-файле), так и ресурсы JTA (соединение настраивается на сервере, в приложении ты по имени получаешь нужный DataSource). 
Потом ты создаёшь классы сущностей. Создаёшь обычный (POJO) класс с аннотацией Entity, описываешь поля, геттеры и сеттеры. Аннотациями можно настраивать всякие штуки: имя таблицы в БД, имя поля, задавать связи, тип получения (LAZY/EAGER), каскадность, автогенерацию первичных ключей и т.д.
Затем надо создать класс, который будет предоставлять интерфейс для работы с сущностями. Обычно, для каждой сущности надо сделать свой класс. Есть несколько вариантов реализации и названия этих классов. NetBeans, например, создаёт классы-фасады: один абстрактный и по-одному фасаду, наследующий абстрактный, на каждую сущность. По ссылке всё наглядно, я думаю. Каждый фасад - это бин (аннотация Stateless). В него инжектится EntityManager:@PersistenceContext(unitName = "AffableBeanPU")
private EntityManager em;
При настроенной связи с БД (в persistence.xml) в em будет нужная реализация этого менеджера, через который и происходит вся магия. Плюсом является то, что все запросы автоматом используют транкзакции.
Ну а потом, в коде, надо просто инжектить этот фасад через аннотацию EJB и использовать его (например, для реализации REST API):import org.foo.example.entities.Foo;
import org.foo.example.facades.FooFacade;

@Path("foo")
@Consumes({"application/json", "application/xml"})
@Produces({"application/json", "application/xml"})
class FooResource {

    @EJB
    FooFacade facade;

    @GET
    public List<Foo> getAll() {
        return facade.findAll();
    }

    @POST
    public Foo create(Foo item) {
        facade.create(item);
        return item;
    }

    @GET
    @Path("{id}")
    public Foo getOne(@PathParam("id") Integer id) {
        return facade.find(id);
    }

    @PUT
    @Path("{id}")
    public Foo update(@PathParam("id") Integer id, Foo item) {
        item.setId(id);
        facade.update(item);
        return item;
    }

    @DELETE
    @Path("{id}")
    public void delete(@PathParam("id") Integer id) {
        facade.remove(facade.find(id));
    }    
}UPD. 
Запилил демо-приложение, можешь взять посмотреть.
Суть такая: ставим wildfly, добавляем пользователя. Запускаем сервер. Можно зайти в админку 127.0.0.1:9990 
Там на вкладке Configuration->Datasources будет 1 источник данных - ExampleDS. Это h2 - встроенная БД, которая крутится в данном случае в оперативке и при перезапуске сервера сбрасывается.
В файле persistence.xml настраиваем ресурсы: указываем имя persistence-unit, и его тип - JTA. Таким образом, ничего локально настраивать не надо, приложение получает всё через ресурс, который настроен на самом сервере, по его имени (java:jboss/datasources/ExampleDS). Единственное, в конфиге указываем <property name="hibernate.hbm2ddl.auto" value="update" /> чтобы таблицы в БД автоматом создавались (если их нет).
В пакете entities лежат 2 сущности: User и Post. Обе аннотированны Entity, таким образом, JPA может с ними работать. Ещё в сущностях присутствуют аннотации для валидации сущностей (это всякие NotNull, Size, Min, Valid и т.д.). Так же, там есть простая двусторонняя связь. В сущности Post есть связь ManyToOne к сущности User, в сущности User есть связь OneToMany со списком постов пользователя. Последняя связь нужна, чтобы обеспечить каскадность на уровне JPA, но геттеров/сеттеров на неё нет, потому что я не хочу, чтобы этот список вылезал при получении пользователя. По-хорошему, надо её убрать, а в таблице post (которая связана с сущностью Post) надо самому прописать каскадность при удалении, потому что пользователь особо не должен знать, что у него в зависимых.
Далее, в пакете dao находятся классы для доступа к сущностям.AbstractDao -  это абстрактный generic-класс, в котором описаны операции для управления хранением сущностей. Все методы там тривиальны, за исключением получения.
Вообще, есть несколько способов получить сущность. Можно использовать простые SQL-запросы, можно указывать именованные запросы (NamedQuery), которые можно описать либо через одноимённую аннотацию, либо в коде. Вторые имеют бонус в виде типобезопасности.
И ещё один из вариантов - это динамические запросы через CriteriaBuilder. JPA генерирует метаклассы для классов, отмеченных аннотацией Entity. Запросы можно строить, в том числе,  используя эти метаклассы. Большим плюсом является то, что такие запросы можно (и нужно) делать типобезопасными (CriteriaQuery, TypedQuery). И IDE не ругается на приведение типов, которое было бы в случае простых нетипизированных запросов. Вообще, по этой ссылке есть подробное описание таких типобезопасных запросов.
Особое внимание к методам findWithLazy и findAllWithLazy. В сущности Post поле owner помечено как связь ManyToOne с ленивым типом получения (fetch = FetchType.LAZY). Просто так такое поле получить трудно: ленивая загрузка работает только в пределах сессии: создалась сессия, запросились данные, сессия закрылась. И ленивые поля по-умолчанию не добавляются к возвращаемому объекту. Есть несколько способов побороть это. Можно убрать ленивость (fetch = FetchType.EAGER). Можно вызвать метод size() для поля-коллекции. Можно вручную получать поля. У меня сделано именно так. В методы findWithLazy и findAllWithLazy передаётся список полей, необходимых для получения. Я создаю запрос на получение корневого элемента: Root<T> root = criteriaQuery.from(entityClass);, а затем в цикле получаю необходимые поля: for (String field : fields) { root.fetch(field); }. При выполнении запроса эти поля присоединятся к результату.
В классах  UserDao и PostDao я указываю аннотацию Stateless для CDI и реализую абстрактный метод getEntityManager() для получения экземпляра PersistenceManager. Сам экземпляр я внедряю через аннотацию PersistenceContext, где в качестве параметра unitName я указываю имя persistence-unit, которое обозначил в persistence.xml.
Ну и наконец, использование классов DAO в приложении (пакет resources). Я создаю простой REST API с помощью JAX-RS. Для каждой сущности создаю по своему ресурсу, в который внедряю через аннотацию EJB нужный DAO-класс. Там, думаю, всё очевидно.
В описании репозитория указано, как запустить и потестить всё это дело. 
Надеюсь, всё понятно.

Худший ответ: Цитата из "Play for Scala"
Play’s original design was intended to support an alternative architecture, whose
model classes include business logic and persistence layer access with their data. This
“encapsulated model” style looks somewhat different from the Java EE style, as shown
in figure 3.5, and typically results in simpler code.
Despite all of this, Play doesn’t have much to do with your domain model. Play
doesn’t impose any constraints on your model, and the persistence API integration it
provides is optional. In the end, you should use whichever architectural style you prefer.
Play2 не навязывает ничего в плане организации бизнес-логики и хранения. Посмотрите примеры (к сожалению в дистре идут только с версиями до 2.2.х), они прозрачно намекают делать анемичной моделью case class, а БЛ и DAO пихать в объект-компаньон.  Кортежи тупо мапяться в case class'ы модели и всё. См. пример computer-database  для Slickи для Anorm
И да, все CRUD операции надо руками прописывать, хотя скафолдинг для DAO пишется запросто на голом JDBC как в сторону таблица -> класс, так и обратно. А можно воспользоваться  чем нибудь готовымИ дался вам этот Slick? Чем людей anorm не устраивает...