I'm somewhat new to Scala and squeryl, but we were all getting along
fine until I tried to add a ManyToMany relation. I'm working with
Scala 2.9.1, Squeryl 0.9.5-rc1 and Microsoft SQL Server 2008 R2 with
jtds 1.2.5. Being something of a novice here, I'll no doubt make all
sorts of obvious bone-headed mistakes, but sometimes that feedback is
valuable, so here are my trials and tribulations with ManyToMany.
First, here's the common typed enumeration, and the table
initializations didn't change:
object PowerRating extends Enumeration {
type PowerRating = Value
val KW25 = Value(25000)
val KW50 = Value(50000)
val KW100 = Value(100000)
val KW160 = Value(160000)
}
...
val partType = table[PartType]
on(partType)(x => declare(
x.id is(primaryKey, unique, indexed)
))
val powerRating = table[PowerRating]
on(powerRating)(x => declare(
x.id is(primaryKey, unique, indexed)
))
// the ManyToMany associating the above two
val billOfMaterials =
manyToManyRelation(powerRating, partType)
.via[BillOfMaterial]((r, p, bom) => (
r.id === bom.powerRatingId,
p.id === bom.partTypeId))
I started with the obvious class implementations based off of the
documentation:
class PartType(val item : String,
val description : String,
val unitPrice : Int,
val partNumber : String) extends KeyedEntity[Int] {
def this() = this("", "", 0, "")
val id : Int = 0
}
class PowerRating(val power : PowerRating.PowerRating,
val description : String) extends
KeyedEntity[PowerRating.PowerRating] {
def this() = this(PowerRating.KW160, "")
def id = power
}
class BillOfMaterial(val powerRatingId : PowerRating.PowerRating,
val partTypeId : Int,
val quantity : Int) extends
KeyedEntity[CompositeKey2[PowerRating.PowerRating, Int]] {
val id = compositeKey(powerRatingId, partTypeId)
}
I get some sort of "assertion failed" error at runtime:
java.lang.AssertionError: assertion failed
at scala.Predef$.assert(Predef.scala:89) ~[na:na]
at org.squeryl.dsl.QueryDsl$
class.org$squeryl$dsl$QueryDsl$
$_splitEquality(QueryDsl.scala:567) ~[squeryl_2.9.1-0.9.5-RC1.jar:
0.9.5-RC1]
at org.squeryl.dsl.QueryDsl
$ManyToManyRelationImpl.<init>(QueryDsl.scala:301)
~[squeryl_2.9.1-0.9.5-RC1.jar:0.9.5-RC1]
at org.squeryl.dsl.QueryDsl
$ManyToManyRelationBuilder.via(QueryDsl.scala:258)
~[squeryl_2.9.1-0.9.5-RC1.jar:0.9.5-RC1]
...
Even if I eliminate all the references to the PowerRating enumeration,
the problem persists.
Turns out, the problem has to do with "def id = power" in the
PowerRating class. If I eliminate the PowerRating enumeration in all
classes and keys, and change the aforementioned def into "val id =
power", then everything works as expected. If try to add back the
enumerations in the keys, then I receive the following error:
java.lang.RuntimeException: error executing alter table
[BillOfMaterial] add constraint [BillOfMaterialCPK] unique()
java.sql.SQLException: Incorrect syntax near ')'.
at org.squeryl.Schema$
class.org$squeryl$Schema$
$_executeDdl(Schema.scala:243) ~[squeryl_2.9.1-0.9.5-RC1.jar:0.9.5-
RC1]
at org.squeryl.Schema$$anonfun$_createConstraintsOfCompositePKs
$1.apply(Schema.scala:277) ~[squeryl_2.9.1-0.9.5-RC1.jar:0.9.5-RC1]
at org.squeryl.Schema$$anonfun$_createConstraintsOfCompositePKs
$1.apply(Schema.scala:275) ~[squeryl_2.9.1-0.9.5-RC1.jar:0.9.5-RC1]
at scala.collection.mutable.ResizableArray
$class.foreach(ResizableArray.scala:60) ~[na:na]
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:44)
~[na:na]
at org.squeryl.Schema
$class._createConstraintsOfCompositePKs(Schema.scala:275)
~[squeryl_2.9.1-0.9.5-RC1.jar:0.9.5-RC1]
at org.squeryl.Schema$class.create(Schema.scala:182)
~[squeryl_2.9.1-0.9.5-RC1.jar:0.9.5-RC1]
...
The docs use "def" to specify the "id" of a KeyedEntity all the time,
so I have no idea why it caused a problem in this case (a bug?).
Enumerations are also just ints according to the docs, so I don't see
any intrinsic problems with using them in keys. Any insight into why
my limited intellect isn't grasping this would be much appreciated!
Sandro