Scala 如何使用新的Slick 2.0 HList来克服22列限制?
我目前正在编写流畅的代码,目标是一个有两个表>22列的旧模式。我该怎么办?在Scala 2.10.3下,2.0-M3在其他方面运行良好。 下面是我目前用于case类/元组的语法。我该怎么办Scala 如何使用新的Slick 2.0 HList来克服22列限制?,scala,tuples,slick,hlist,Scala,Tuples,Slick,Hlist,我目前正在编写流畅的代码,目标是一个有两个表>22列的旧模式。我该怎么办?在Scala 2.10.3下,2.0-M3在其他方面运行良好。 下面是我目前用于case类/元组的语法。我该怎么办 case类Joiner( id:Int, 名称:选项[字符串], 联系人:选项[字符串] ) 类Joiner(tag:tag)扩展表[Joiner](tag,“Joiner”){ def id=列[Int](“id”,O.PrimaryKey,O.AutoInc,O.DBType(“Int(11)”) def
case类Joiner(
id:Int,
名称:选项[字符串],
联系人:选项[字符串]
)
类Joiner(tag:tag)扩展表[Joiner](tag,“Joiner”){
def id=列[Int](“id”,O.PrimaryKey,O.AutoInc,O.DBType(“Int(11)”)
def name=column[Option[String](“name”,O.DBType(“varchar(255)”)
def contact=column[Option[String](“contact”,O.DBType(“text”))
def*=(id、姓名、联系人)(Joiner.tuple、Joiner.unapply)
}
val joiners=TableQuery[joiners]
我在示例中没有看到任何内容,在最新更新的文档中只有一个简短的提及。我是Scala的新手,而且很圆滑。定义 Scala>=2.10.4-RC2时(也由Slick 2.0.0代码生成器发出): 上述情况导致Scala 2.10.3/2.10.4-RC1中的编译时间呈指数级增长。由于编译时间过长,超过26列不可行 无需映射到case类的Scala 22的变通方法(Scala 2.10中的最大字段限制为22)
另外:不要使用O.Nullable。改用
列[选项[字符串]]
。这段代码是为了演示在Scala v2.10.4_RC1中,当列数超过26列时仍然影响编译器的性能问题(它只是卡住了)
import java.sql.Timestamp
import scala.slick.driver.MySQLDriver.simple._
import scala.slick.collection.heterogenous._
// **** Uncomment this ****
//import scala.slick.collection.heterogenous.syntax._
object DealSlick {
class Deals(tag: Tag) extends Table[
Long :: String :: String :: Option[String] :: Option[String] :: Option[String] ::
// urlKeywords
Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// extTags
Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// currency
Option[String] :: Option[String] ::
// price
Option[Double] :: Option[Double] :: Option[Double] :: Option[Double] ::
// extStatus
Option[String] :: Option[String] :: Option[Int] :: Option[Int] ::
/* If you add more columns the compiler get stuck in a never-ending
* compilation possibly related to
* https://github.com/slick/slick/issues/577
*/
// endAt
Option[Timestamp] :: /*Option[Timestamp] :: Option[Timestamp] :: Option[Timestamp] ::
// timeZoneOffset
Option[Int] :: Option[String] :: Option[Timestamp] :: Option[String] ::
// locationName
Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// city
Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// latitude
Option[Double] :: Option[Double] ::
// merchantTitle
Option[String] :: */
// End of list
HNil
](tag, "deal") {
def id = column[Long]("id", O.PrimaryKey)
def siteName = column[String]("partner_site_name", O.NotNull)
def siteDomain = column[String]("partner_site_domain", O.NotNull)
def localeLanguage = column[Option[String]]("deal_language")
def localeCountry = column[Option[String]]("deal_country")
def extId = column[Option[String]]("deal_ext_id")
def urlKeywords = column[Option[String]]("deal_url_keywords")
def keywords = column[Option[String]]("deal_keywords")
def extCategories = column[Option[String]]("deal_ext_categories")
def categoryText = column[Option[String]]("deal_category_text")
def coverage = column[Option[String]]("deal_coverage")
def extTags = column[Option[String]]("deal_ext_tags")
def title = column[Option[String]]("deal_title")
def description = column[Option[String]]("deal_description")
def extImage = column[Option[String]]("deal_ext_image")
def url = column[Option[String]]("deal_url")
def currency = column[Option[String]]("deal_currency")
def currencySym = column[Option[String]]("deal_currency_sym")
def price = column[Option[Double]]("deal_price")
def saving = column[Option[Double]]("deal_saving")
def discount = column[Option[Double]]("deal_discount")
def dvalue = column[Option[Double]]("deal_value")
def extStatus = column[Option[String]]("deal_ext_status")
def status = column[Option[String]]("deal_status")
def soldQty = column[Option[Int]]("deal_sold_qty")
def leftQty = column[Option[Int]]("deal_left_qty")
def endAt = column[Option[Timestamp]]("deal_end_at")
/* def endAtUtc = column[Option[Timestamp]]("deal_end_at_utc")
def expiresAt = column[Option[Timestamp]]("deal_expires_at")
def expiresAtUtc = column[Option[Timestamp]]("deal_expires_at_utc")
def timeZoneOffset = column[Option[Int]]("time_zone_offset")
def timeZoneName = column[Option[String]]("time_zone_name")
def timeGrabbed = column[Option[Timestamp]]("time_grabbed")
def timeRemainingStr = column[Option[String]]("time_remaining_str")
def locationName = column[Option[String]]("location_name")
def address = column[Option[String]]("location_address")
def street = column[Option[String]]("location_street")
def postalCode = column[Option[String]]("location_postalcode")
def city = column[Option[String]]("location_city")
def province = column[Option[String]]("location_province")
def region = column[Option[String]]("location_region")
def state = column[Option[String]]("location_state")
def country = column[Option[String]]("location_country")
def latitude = column[Option[Double]]("location_latitude")
def longitude = column[Option[Double]]("location_longitude")
def merchantTitle = column[Option[String]]("merchant_title")
*/
def * = (id :: siteName :: siteDomain :: localeLanguage :: localeCountry :: extId ::
urlKeywords :: keywords :: extCategories :: categoryText :: coverage ::
extTags :: title :: description :: extImage :: url ::
currency :: currencySym :: price :: saving :: discount :: dvalue ::
extStatus :: status :: soldQty :: leftQty ::
endAt :: /*endAtUtc :: expiresAt :: expiresAtUtc ::
timeZoneOffset :: timeZoneName :: timeGrabbed :: timeRemainingStr ::
locationName :: address :: street :: postalCode ::
city :: province :: region :: state :: country ::
latitude :: longitude ::
merchantTitle :: */
HNil )
}
}
**更新**
在更新到Scala 2.10.4-RC2后,编译器在编译过程中会进一步执行一些步骤,但它再次陷入困境:
以下是仅定义少数表列时的编译器输出
[信息][加载的类文件/Users/max/.ivy2/cache/com.typesafe.slick/slick_2.10/jars/slick_2.10-2.0.0.jar(scala/slick/backend/DatabaseComponent.class)以1ms为单位]
[info][loaded class file/Users/max/.ivy2/cache/com.typesafe.slick/slick_2.10/jars/slick_2.10-2.0.0.jar(scala/slick/lifted/ShapedValue.class)以2ms为单位]
[info][loaded package loader util in 2ms]当使用超过26列时,此输出不会打印在屏幕上如果我不使用case类,我可以定义一个常规类,还是需要在某种列表中列出所有类型?另外,对于“*”投影中的选项列,我是否仍然使用尾随的“?”,或者这是推断的?。?也可以说是推断出来的。你不需要它们。我不确定你所说的列出所有类型是什么意思,但是你可以把你的行映射到任何东西。概念是
(factoryFunction,extractorFunction)
我应该用什么来代替case类,因为在Scala 2.11之前,case类只限于22列?如何将过去的case类声明为HList,并将其作为类型参数传递给table类?我更新示例以显示类型。关于case类,您可以省略它。您将无法按结果中的名称访问列,只能按位置r(2)
。如果您确实想要命名访问,您可以通过编写适当的工厂和提取器函数映射到
中的普通类。根据Vogt先生的建议更正。也张贴在这里:请在将来交叉链接。对不起,我收到一条消息,我的Google Groups帖子被拒绝,因此我认为它不起作用。注意:如果有人试图遵循此解决方案(如下)截至Slick 2.0-M3,HList代码无法工作——编译超过22列(以指数形式增长)将需要数小时和千兆字节的RAM,以确保实现是正确的(据我们所知)。然而,目前它似乎在Scala编译器中触发了指数级编译时间,对于25或更大的大小,这会严重影响您。我们将研究如何解决这个问题。这可能是从RC1开始解决的,但我不确定。我试图跟踪我在中看到的提交和bug跟踪消息,但无法跟踪。如果你想修补Scala或者自己光滑一些,有一些修复方法。Christopher,谢谢你的提示,但是我已经试过Scala v2.10.4-RC2了,我必须说我注意到编译器在这一点上不再阻塞,但它在下一步会被卡住。如果您和您的团队认为值得对此问题进行调查,您可以使用我发布的代码进行测试。
import scala.slick.collection.heterogenous._
import syntax._
class Joiners(tag: Tag) extends Table[
Int :: Option[String] :: Option[String] :: HNil
](tag, "joiner") {
...
def * = id :: name :: contact :: HNil
}
import scala.slick.collection.heterogenous._
import syntax._
class Joiners(tag: Tag) extends Table[
HCons[Int, HCons[Option[String], HCons[Option[String], HNil]]]
](tag, "joiner") {
...
def * = id :: name :: contact :: HNil
}
Joiners.run.map( r => r(2) ) // Gets column contact. It's typesafe. .apply is a macro. Only works for literals not for variables as positions.
import java.sql.Timestamp
import scala.slick.driver.MySQLDriver.simple._
import scala.slick.collection.heterogenous._
// **** Uncomment this ****
//import scala.slick.collection.heterogenous.syntax._
object DealSlick {
class Deals(tag: Tag) extends Table[
Long :: String :: String :: Option[String] :: Option[String] :: Option[String] ::
// urlKeywords
Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// extTags
Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// currency
Option[String] :: Option[String] ::
// price
Option[Double] :: Option[Double] :: Option[Double] :: Option[Double] ::
// extStatus
Option[String] :: Option[String] :: Option[Int] :: Option[Int] ::
/* If you add more columns the compiler get stuck in a never-ending
* compilation possibly related to
* https://github.com/slick/slick/issues/577
*/
// endAt
Option[Timestamp] :: /*Option[Timestamp] :: Option[Timestamp] :: Option[Timestamp] ::
// timeZoneOffset
Option[Int] :: Option[String] :: Option[Timestamp] :: Option[String] ::
// locationName
Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// city
Option[String] :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
// latitude
Option[Double] :: Option[Double] ::
// merchantTitle
Option[String] :: */
// End of list
HNil
](tag, "deal") {
def id = column[Long]("id", O.PrimaryKey)
def siteName = column[String]("partner_site_name", O.NotNull)
def siteDomain = column[String]("partner_site_domain", O.NotNull)
def localeLanguage = column[Option[String]]("deal_language")
def localeCountry = column[Option[String]]("deal_country")
def extId = column[Option[String]]("deal_ext_id")
def urlKeywords = column[Option[String]]("deal_url_keywords")
def keywords = column[Option[String]]("deal_keywords")
def extCategories = column[Option[String]]("deal_ext_categories")
def categoryText = column[Option[String]]("deal_category_text")
def coverage = column[Option[String]]("deal_coverage")
def extTags = column[Option[String]]("deal_ext_tags")
def title = column[Option[String]]("deal_title")
def description = column[Option[String]]("deal_description")
def extImage = column[Option[String]]("deal_ext_image")
def url = column[Option[String]]("deal_url")
def currency = column[Option[String]]("deal_currency")
def currencySym = column[Option[String]]("deal_currency_sym")
def price = column[Option[Double]]("deal_price")
def saving = column[Option[Double]]("deal_saving")
def discount = column[Option[Double]]("deal_discount")
def dvalue = column[Option[Double]]("deal_value")
def extStatus = column[Option[String]]("deal_ext_status")
def status = column[Option[String]]("deal_status")
def soldQty = column[Option[Int]]("deal_sold_qty")
def leftQty = column[Option[Int]]("deal_left_qty")
def endAt = column[Option[Timestamp]]("deal_end_at")
/* def endAtUtc = column[Option[Timestamp]]("deal_end_at_utc")
def expiresAt = column[Option[Timestamp]]("deal_expires_at")
def expiresAtUtc = column[Option[Timestamp]]("deal_expires_at_utc")
def timeZoneOffset = column[Option[Int]]("time_zone_offset")
def timeZoneName = column[Option[String]]("time_zone_name")
def timeGrabbed = column[Option[Timestamp]]("time_grabbed")
def timeRemainingStr = column[Option[String]]("time_remaining_str")
def locationName = column[Option[String]]("location_name")
def address = column[Option[String]]("location_address")
def street = column[Option[String]]("location_street")
def postalCode = column[Option[String]]("location_postalcode")
def city = column[Option[String]]("location_city")
def province = column[Option[String]]("location_province")
def region = column[Option[String]]("location_region")
def state = column[Option[String]]("location_state")
def country = column[Option[String]]("location_country")
def latitude = column[Option[Double]]("location_latitude")
def longitude = column[Option[Double]]("location_longitude")
def merchantTitle = column[Option[String]]("merchant_title")
*/
def * = (id :: siteName :: siteDomain :: localeLanguage :: localeCountry :: extId ::
urlKeywords :: keywords :: extCategories :: categoryText :: coverage ::
extTags :: title :: description :: extImage :: url ::
currency :: currencySym :: price :: saving :: discount :: dvalue ::
extStatus :: status :: soldQty :: leftQty ::
endAt :: /*endAtUtc :: expiresAt :: expiresAtUtc ::
timeZoneOffset :: timeZoneName :: timeGrabbed :: timeRemainingStr ::
locationName :: address :: street :: postalCode ::
city :: province :: region :: state :: country ::
latitude :: longitude ::
merchantTitle :: */
HNil )
}
}