Database Slick 3连接查询一对多关系

Database Slick 3连接查询一对多关系,database,scala,slick,slick-3.0,Database,Scala,Slick,Slick 3.0,想象一下下面的关系 一本书由许多章节组成,一章只属于一本书。经典的一对多关系 我将其建模为: case class Book(id: Option[Long] = None, order: Long, val title: String) class Books(tag: Tag) extends Table[Book](tag, "books") { def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc) def or

想象一下下面的关系

一本书由许多章节组成,一章只属于一本书。经典的一对多关系

我将其建模为:

case class Book(id: Option[Long] = None, order: Long, val title: String)

class Books(tag: Tag) extends Table[Book](tag, "books")
{
  def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
  def order = column[Long]("order")
  def title = column[String]("title")

  def * = (id, order, title) <> (Book.tupled, Book.unapply)
  def uniqueOrder = index("order", order, unique = true)

  def chapters: Query[Chapters, Chapter, Seq] = Chapters.all.filter(_.bookID === id)
}

object Books
{
  lazy val all = TableQuery[Books]
  val findById = Compiled {id: Rep[Long] => all.filter(_.id === id)}

  def add(order: Long, title: String) = all += new Book(None, order, title)
  def delete(id: Long) = all.filter(_.id === id).delete

//  def withChapters(q: Query[Books, Book, Seq]) = q.join(Chapters.all).on(_.id === _.bookID)

  val withChapters = for
  {
    (Books, Chapters) <- all join Chapters.all on (_.id === _.bookID)
  } yield(Books, Chapters)
}

case class Chapter(id: Option[Long] = None, bookID: Long, order: Long, val title: String)

class Chapters(tag: Tag) extends Table[Chapter](tag, "chapters")
{
  def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
  def bookID = column[Long]("book_id")
  def order = column[Long]("order")
  def title = column[String]("title")

  def * = (id, bookID, order, title) <> (Chapter.tupled, Chapter.unapply)
  def uniqueOrder = index("order", order, unique = true)

  def bookFK = foreignKey("book_fk", bookID, Books.all)(_.id.get, onUpdate = ForeignKeyAction.Cascade, onDelete = ForeignKeyAction.Restrict)
}

object Chapters
{
  lazy val all = TableQuery[Chapters]
  val findById = Compiled {id: Rep[Long] => all.filter(_.id === id)}

  def add(bookId: Long, order: Long, title: String) = all += new Chapter(None, bookId, order, title)
  def delete(id: Long) = all.filter(_.id === id).delete
}
以及:

object Books
{
    //...
    val withChapters = for
    {
        (Books, Chapters) <- all join Chapters.all on (_.id === _.bookID)
    } yield(Books, Chapters)
}
像这样,我得到一个
索引outofboundsexception

我用这个作为我的方法:

object Books
{
      def withChapters(id: Long) = Books.all.filter(_.id === id) join Chapters.all on (_.id === _.bookID)
}
此外:

logback.xml
如下所示:

class BookWithChapters extends FlatSpec with Matchers with ScalaFutures with BeforeAndAfter
{
  val db = Database.forConfig("db.test.h2")

  private val books = Books.all
  private val chapters = Chapters.all

  before { db.run(setup) }
  after {db.run(tearDown)}

  val setup = DBIO.seq(
    (books.schema).create,
    (chapters.schema).create
  )

  val tearDown = DBIO.seq(
    (books.schema).drop,
    (chapters.schema).drop
  )

  "Books" should "consist of chapters" in
  {
    db.run(
      DBIO.seq
      (
        Books.add(0, "Book #1"),
        Chapters.add(0, 0, "Chapter #1")
      )
    )

    //whenReady(db.run(Books.withChapters(books).result)) {
    whenReady(db.run(Books.withChapters(1).result)) {
    result => {
      //  result should have length 1
        print(result(0)._1)
      }
    }
  }
}
<configuration>
    <logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG/>
</configuration>


要翻译您的查询

SELECT * FROM books b JOIN chapters c ON books.id == c.book_id WHERE books.id = 10
…为了顺利,我们可以
过滤
书籍

val bookTenChapters = 
  Books.all.filter(_.id === 10L) join Chapters.all on (_.id === _.bookID)
这将提供一个查询,返回
Seq[(书籍、章节)]
。如果要选择不同的书籍,可以使用不同的筛选表达式

或者,您可能更喜欢在联接上进行筛选:

val everything = 
   Books.all join Chapters.all on (_.id === _.bookID)

val bookTenChapters = 
  everything.filter { case (book, chapter) => book.id === 10L }
这可能会更接近你的加入。检查使用数据库生成的SQL,以查看您更喜欢哪个

您可以通过创建
src/main/resources/logback.xml文件记录查询,并设置:

 <logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG"/>


我有一本书。您需要将xml文件中的
INFO
更改为
DEBUG
,例如chapter-01文件夹。

我在
res/main
下创建了.xml文件,找到了它,但日志在哪里?它应该进入控制台吗?我尝试了
info
,但只得到了异常,没有查询字符串。有什么我错过的吗?还有,谢谢,但对我来说不起作用,我不知道为什么。我更新了我的问题。在XML配置中需要一个“appender”,在build.XML中还需要一个日志库。这个要点提供了一个SBT依赖项和一个完整的日志配置,应该对您有用:谢谢,我已经有了它(版本1.1.3用于logback)(取自您的示例项目;),但是SBT一直抱怨根目录是不允许的。现在,无论出于什么原因(我没有改变任何事情),它都能工作。谢谢!查询仍然没有成功,因为您的测试似乎没有等待插入两条测试记录?这就是你遇到的问题,还是其他什么问题不起作用?
 <logger name="slick.jdbc.JdbcBackend.statement" level="DEBUG"/>