我今天一直在苦恼这个问题。我不知道是否有好的解决方案,但我可以提供几个选项。
### 补丁Slick驱动程序以允许等式测试
我正在使用MySQL数据库,该数据库支持将字节数据作为字符串发送的语法:
mysql> desc user;
+
| Field | Type | Null | Key | Default | Extra |
+
| user_uuid | binary(16) | NO | PRI | NULL | |
| email | varchar(254) | NO | UNI | NULL | |
| display_name | varchar(254) | NO | | NULL | |
| password_hash | varchar(254) | YES | | NULL | |
+
4 rows in set (0.01 sec)
mysql> select * from user where user_uuid = x'e4d369040f044b6e9561765c356907d3';
+
| user_uuid | email | display_name | password_hash |
+
| ???????????? | foo@example.com | Foo | NULL |
+
1 row in set (0.00 sec)
为了表明UUID是正确的:
mysql> select hex(user_uuid), email, display_name from user where user_uuid = x'e4d369040f044b6e9561765c356907d3';
+
| hex(user_uuid) | email | display_name |
+
| E4D369040F044B6E9561765C356907D3 | foo@example.com | Foo |
+
基于此,下面的补丁程序应用于
MySQLDriver.scala
(版本1.0.1)效果很好:
$ git diff
diff --git a/src/main/scala/scala/slick/driver/MySQLDriver.scala b/src/main/scala/scala/slick/driver/
index 84a667e..1aa5cca 100644
--- a/src/main/scala/scala/slick/driver/MySQLDriver.scala
+++ b/src/main/scala/scala/slick/driver/MySQLDriver.scala
@@ -174,9 +174,15 @@ trait MySQLDriver extends ExtendedDriver { driver =>
}
}
+ import java.util.UUID
+
override val uuidTypeMapperDelegate = new UUIDTypeMapperDelegate {
override def sqlType = java.sql.Types.BINARY
override def sqlTypeName = "BINARY(16)"
+
+ override def valueToSQLLiteral(value: UUID): String =
+ "x'"+value.toString.replace("-", "")+"'"
}
}
}
使用这个功能,你可以编写如下代码:
def findUserByUuid(uuid: UUID): Option[UserRecord] = db.withSession {
val query = (for (u <- UserRecordTable if u.uuid === uuid) yield u)
query.firstOption
}
我不确定您正在使用哪个数据库,但类似的方法可能有效。我还没有对此进行性能测试。
将UUID编码为字节数组
有几种选项可以避免代码修补。
使用
http://nineofclouds.blogspot.com.au/2013/04/storing-uuids-with-anorm.html中的UUIDHelper,您可以将UUID编码为字节数组并执行静态查询。有些不太优雅,但可行的方式是:
import UuidHelper
implicit object SetUUID extends SetParameter[UUID] {
def apply(v: UUID, pp: PositionedParameters) { pp.setBytes(UuidHelper.toByteArray(v)) }
}
implicit val getUserRecordResult = GetResult(r =>
UserRecord(UuidHelper.fromByteArray(r.nextBytes()), r.<<, r.<<, r.<<)
)
val userByUuid = StaticQuery[UUID, UserRecord] + "select * from user where user_uuid = ?"
val user = userByUuid(user.uuid).first
将UUID编码为十六进制字符串
下面的方法可能不是最优雅的,但是出于完整性考虑而包含在内:
implicit val getUserRecordResult = GetResult(r => UserRecord(UuidHelper.fromByteArray(r.nextBytes()), r.<<, r.<<, r.<<))
val uuid = user.uuid.toString.replace("-", "")
val userByUuid = StaticQuery.queryNA[UserRecord](s"select * from user where user_uuid = x'$uuid'")
val user = userByUuid().first
HTH
编辑:下面是针对主分支的拉取请求。请注意,此拉取请求针对主分支(2.0.0),但我仅在1.0.1上成功测试过。
https://github.com/slick/slick/pull/240