首先,我必须提到我对Slick来说还是新手,主要是学习,每次都发现一些奇怪的情况,比如这个。
我有一个案例类地址为Slick表定义如下:
package model
import driver.PGDriver.api._
import format.DateTimeFormat._
import org.joda.time.DateTime
import play.api.libs.json._
import slick.lifted.Tag
case class Address(id: Option[Int] = None,
countryId: Option[Int] = None,
continentId: Option[Int] = None,
stateId: Option[Int] = None,
address1: String,
address2: Option[String],
city: String,
zip: String,
createdAt: DateTime = DateTime.now,
updatedAt: DateTime = DateTime.now,
deletedAt: Option[DateTime] = None,
createdBy: Option[String] = None,
updatedBy: Option[String] = None)
object Addresses {
val addresses = TableQuery[Addresses]
implicit lazy val addressFormat: Format[Address] = Json.format[Address]
Json.toJson[DateTime](DateTime.now)
}
class Addresses(tag: Tag) extends Table[Address](tag, "address") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def countryId = column[Option[Int]]("country_id")
def continentId = column[Option[Int]]("continent_id")
def stateId = column[Option[Int]]("state_id")
def address1 = column[String]("address1", O.SqlType("character varying(255)"))
def address2 = column[Option[String]]("address1", O.SqlType("character varying(255)"))
def city = column[String]("city", O.SqlType("character varying(255)"))
def zip = column[String]("zip", O.SqlType("character varying(30)"))
def createdAt = column[DateTime]("createdat")
def updatedAt = column[DateTime]("updatedat")
def deletedAt = column[Option[DateTime]]("deletedat")
def createdBy = column[Option[String]]("createdby", O.SqlType("character varying(255)"))
def updatedBy = column[Option[String]]("updatedby", O.SqlType("character varying(255)"))
override def * =
(
id.?,
countryId,
continentId,
stateId,
address1,
address2,
city,
zip,
createdAt,
updatedAt,
deletedAt,
createdBy,
updatedBy
) <> (Address.tupled, Address.unapply)
def addressStateIdIdx = index("address_state_id_idx", stateId)
def state =
foreignKey("address_state_id_fkey", stateId, GeoAreas.areas)(
_.id.?,
onUpdate = ForeignKeyAction.Cascade,
onDelete = ForeignKeyAction.Restrict
)
def addressCountryIdIdx = index("address_country_id_idx", countryId)
def country =
foreignKey("address_country_id_fkey", countryId, GeoAreas.areas)(
_.id.?,
onUpdate = ForeignKeyAction.Cascade,
onDelete = ForeignKeyAction.Restrict
)
def addressContinentIdIdx = index("address_continent_id_idx", continentId)
def continent =
foreignKey("address_continent_id_fkey", continentId, GeoAreas.areas)(
_.id.?,
onUpdate = ForeignKeyAction.Cascade,
onDelete = ForeignKeyAction.Restrict
)
}
这不是我唯一通过Slick工作的类,但是,出于某种原因,只是因为这个类,我在尝试使用join创建查询时遇到异常。像这样:
def search(searchCriteria: SearchCriteria,
readyOnly: Boolean,
drop: Long = 0,
take: Long = 100): Future[Seq[(School, Option[Address])]] = {
val q = for {
(school, address) <- Schools.schools joinLeft Addresses.addresses on (_.addressId === _.id)
if List(
Some(school.deletedAt.isEmpty),
searchCriteria.school.name.map(n => school.name.toLowerCase like s"%${n.toLowerCase}%"),
searchCriteria.school.ready.map(r => school.ready === r)
).collect({ case Some(criteria) => criteria }).reduceLeftOption(_ && _).getOrElse(true: Rep[Boolean])
} yield (school, address)
db.run(q.drop(drop).take(take).result)
}
我得到的例外是:
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[ClassCastException: scala.Some cannot be cast to java.lang.String]]
在这一点上,我甚至不知道从哪里开始寻找问题。 这个类与我拥有的其他类非常相似。所有其他人工作正常。 一切都编译没有问题。 该异常仅在运行时抛出。
我错过了什么? 谢谢,
更新
我可能已经找到了问题,但是,我不确定如何解决它,为什么会发生这种情况。 正在执行的实际查询是:
SELECT
x2."id",
x2."address_id",
x2."name",
x2."about",
x2."number_of_students",
x2."website_url",
x2."media_id",
x2."slug",
x2."short_description",
x2."ready",
x2."classrooms",
x2."year_established",
x2."display_copyright",
x2."createdat",
x2."updatedat",
x2."deletedat",
x2."createdby",
x2."updatedby",
x2."dli_number",
(CASE WHEN (x3."id" IS NULL)
THEN NULL
ELSE 1 END),
x3."id",
x3."country_id",
x3."continent_id",
x3."state_id",
x3."address1",
x3."address1",
x3."city",
x3."zip",
x3."createdat",
x3."updatedat",
x3."deletedat",
x3."createdby",
x3."updatedby"
FROM "school" x2 LEFT OUTER JOIN "address" x3 ON x2."address_id" = x3."id"
WHERE ((x2."deletedat" IS NULL) AND (lower(x2."name") LIKE '%a%')) AND (x2."ready" = TRUE)
LIMIT 100
OFFSET 0
作为选择的一部分,有一些奇怪的case
。为什么会这样?我做错了什么?
更新#2
另一方面,由于不知道如何灵活地读取查询的行,我不确定这个case
语句是否会导致原始问题。
但是,我仍然被困住了。
更新#3
所以,我只是尝试了最简单的查询,只包含地址表,如下所示:
def all(): Future[Seq[Address]] = db.run(Addresses.addresses.filter(_.deletedAt.isEmpty).result)
我仍然得到同样的例外。
更新#4
这是实际的地址表:
create table address
(
id bigserial not nullconstraint address_pkey primary key,
country_id bigint constraint address_country_id_fkey references geo_area on update cascade on delete restrict,
continent_id bigint constraint address_continent_id_fkey references geo_area on update cascade on delete restrict,
state_id bigint constraint address_state_id_idx references geo_area on update cascade on delete restrict,
address1 varchar(255) not null,
address2 varchar(255),
city varchar(255) not null,
zip varchar(30) not null,
deletedat timestamp with time zone,
createdat timestamp with time zone not null,
updatedat timestamp with time zone not null,
createdby varchar(255),
updatedby varchar(255)
);
create index address_country_id_idx on address (country_id);
create index address_continent_id_idx on address (continent_id);
create index address_state_id_idx on address (state_id);
答案 0 :(得分:1)
我感觉这是非常愚蠢的事情,我是对的。 @Tyler,谢谢你指点我正确的方向 问题出在这里:
def address1 = column[String]("address1", O.SqlType("character varying(255)"))
def address2 = column[Option[String]]("address1", O.SqlType("character varying(255)"))
了解address2
的定义方式。这两个有重复的列名。所以显然它应该是:
def address1 = column[String]("address1", O.SqlType("character varying(255)"))
def address2 = column[Option[String]]("address2", O.SqlType("character varying(255)"))
像往常一样,例外情况是无用的:)