Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a m:n relation with additional attributes in Squeryl?

Given a legacy database with a m:n relation and some additional attributes for the relation, how can this defined with squeryl. At the end the tables should look like this:


   +--------------+      +---------------+      +----------------+
   | TableA       |      | Rel_A_B       |      | TableB         |
   +--------------+ ____ +---------------+ ____ +----------------+
   | id: Int      |      | tableA: int   |      | compkey_1: int |
   | (more attrs) |      | tableB_1: int |      | compkey_2: int |
   +--------------+      | tableB_2: int |      | (more attrs)   |
                         | value: Varchar|      +----------------+
                         | date: Date    |
                         +---------------+

Theres no problem in defining the three tables manually with squeryl. However, as far as I understand the documentation at the moment (0.9.4) there is no possibility to define a many-to-many relationship with additional attributes for the relation.

That's why I defined three tables and two one-to-many relations:


// TableA
class TableA(val id: Int, ...) extends KeyedEntity[Int] {
    def this() = this(0, ...)
}

// TableB
class TableB(val compkey1: Int, val compkey2: Int, ...) 
        extends KeyedEntity[CompositeKey2[Int, Int]] {

    def id = CompositeKey2(compkey1, compkey2)
}

// Rel_A_B
class RelAB(val tabA: Int, val tabB1: Int, val tabB2: Int, val value: String, 
            val date: Date) extends KeyedEntity[CompositeKey3[Int, Int, Int]] {

    def id = CompositeKey3(tabA, tabB1, tabB2)
}

It's easy to define the relation between TableA and RelAB. I use an ordinary one-to-many relation:


val relA =
    oneToManyRelation(tableA, relAB).
    via((a, r) => a.id === r.tableA)

But I don't see a way to define the second relation. I already tried to define an additional composite value on the relation table (named compkeyB) containing just the columns from tableB and compare it to the composite key of tableB, but this doesn't work:


val relB =
    oneToManyRelation(tableB, relAB).
    via((b, r) => b.id === r.compkeyB)

It throws a "type mismatch" exception:

found   : org.squeryl.dsl.ast.LogicalBoolean
required: org.squeryl.dsl.ast.EqualityExpression

Any ideas how to solve this?

like image 374
Steffen Avatar asked Jul 04 '11 11:07

Steffen


1 Answers

You are being bitten by this limitation :

http://www.assembla.com/spaces/squeryl/tickets/25-compositekeys-cannot-be-the-binding-expression-for-relations

like image 154
Max L. Avatar answered Oct 11 '22 13:10

Max L.