Я присоединился к гордым рядам людей, пытающихся использовать Squeryl в качестве рамки ORM для веб-приложения. (Для записи я использую Scalatra в качестве фактической веб-структуры, но я не думаю, что это вопрос Scalatra.) Это означает, что я присоединился к рядам людей, пытающихся создать эффективный уровень абстракции, чтобы DRY наш общие операции. Например, довольно часто можно увидеть примеры, как так:Абстрактные операции CRUD с использованием Squeryl и базового класса
// First Model
package com.myproj
import com.myproj.Schema
class Foo() extends KeyedEntity {
val id = 0
def getAll() = { from(Schema.Foo)(s => select(s)) }
}
// Different Model
package com.myproj
import com.myproj.Schema
class Bar() extends KeyedEntity {
val id = 0
def getAll() = { from(Schema.Boo)(s => select(s)) }
}
Итак, с одной стороны, я рою как синтаксис скупых Squeryl есть. С другой: это довольно повторяющийся. То, что я хочу, больше похоже на:
// Base
class BaseEntity extends KeyedEntity {
val id = 0
def getAll() = { from(table)(s => select(s)) }
}
// New model
class Foo extends BaseEntity
// New model
class Bar extends BaseEntity
У меня в основном такая работа. Расширение KeyedEntity
довольно прямолинейно. Есть только одна проблема: как вы определяете таблицу в BaseEntity
, чтобы классы, расширяющие ее, могли получить к ней доступ? Честно говоря, это в корне может быть вопросом о том, что у меня недостаточно сложное понимание системы типа Scala. Я все равно представляю его здесь.
Я попробовал несколько вещей:
- Декларирование
val table
в абстрактномBaseEntity
. Это привело меня к довольно смешному типу проверки.val table: Table[T]
работает только в том случае, если я также определяю T как тип, а затем дочерние классы вызывают ошибки компилятора, когда они пытаются предоставить таблицу другого типа. - Напишите базовый класс, чтобы ожидать, что таблицы будут переданы в качестве аргумента для каждой функции. Это означает, что каждая модель все еще должна вызывать ее родительский метод для передачи аргумента
table
. - Я взломал с помощью this SO post, который использует
TypeTags
. Однако плакат не предоставил достаточно информации для меня, чтобы понять его реализацию. Вышеупомянутый сообщение SO имеет комментарий, в котором предлагается метод org.squeryl.Schema.findTablesFor. Опять же с потенциальными проблемами новичков: я не добился успеха в том, как реализовать это как ответ. Я пытался что-то вроде:
класс BaseEntity {
валь таблицы = findTablesFor (это)
}
Но тогда, я вернусь итератор, и я немного не уверен, что делать это.
So. Есть ли «правильный» способ сделать это? Разумеется, есть чистый способ перемещения операций CRUD в базовый класс - я просто не могу понять, как это понять.
Редактировать
Итак, вот что у меня есть, используя Squeryl 9.5-6:
// Schema
package com.myproj.schema
object MySchema extends Schema {
val foo = table[Foo]("foos")
val bar = table[Bar]("bars")
}
// BaseEntity
package com.myproj.models
import com.myproj.schema.MySchema
abstract class BaseEntity extends Keyedentity[Long] {
val id: Long = 0
val table = MySchema.findTablesFor(this).head
}
// Class
package com.myproj.models
case class Foo (
val name: String,
val extra: Option[String]
) extends BaseEntity {
def this() = this("", None)
}
установки, как это. findTablesFor
всегда возвращает пустой итератор. Он компилируется, но выдает ошибки во время выполнения, пытаясь вызвать головку на пустой итератор (как вы сказали, это будет). Обработка ошибки не является проблемой; неспособность найти таблицу kinda есть.
Мысли?
Прежде всего, измените элемент таблицы на def или, по крайней мере, на ленивый val, чтобы отложить оценку. Вы можете увидеть, что findTablesFor делает здесь: https://github.com/max-l/Squeryl/blob/79fd98876e62044e87521c291e68b4a961cb6ebb/src/main/scala/org/squeryl/Schema.scala#L78. Определение таблицы добавит ее в коллекцию _tables: https://github.com/max-l/Squeryl/blob/79fd98876e62044e87521c291e68b4a961cb6ebb/src/main/scala/org/squeryl/Schema.scala#L338. Я могу только представить, что это порядок операций. –
Hrm. К сожалению, ни «lazy val table», ни 'def table' не имеют никакого значения - он работает, но все равно не находит таблицы. Я использую Scala 2.10.2 - возможно ли это проблема совместимости? – Gastove
(Для записи: если я вызываю функции squeryl гораздо более явно - скажем, но выполняю 'from (MySchema.Foo) (s => select (s))' - он отлично работает, как и MySchema.create. .) – Gastove