ScalikeJDBC的Scala SQL查询DSL

Scala原生编写了大量SQL API。 曼努埃尔·伯恩哈特(Manuel Bernhardt)在其帖子中总结了一个不错的收藏在此Stack Overflow问题中可以看到Scala SQL API的另一个集合。

我们要特别关注的一个API是ScalikeJDBC获得许可的ASL 2.0 ),该API最近已经发布了类似于jOOQ的SQL查询DSL API。 请参阅此处的完整文档:

http://scalikejdbc.org/documentation/query-dsl.html

几个例子:

val orders: List[Order] = withSQL {
  select
    .from(Order as o)
    .innerJoin(Product as p).on(o.productId, p.id)
    .leftJoin(Account as a).on(o.accountId, a.id)
    .where.eq(o.productId, 123)
    .orderBy(o.id).desc
    .limit(4)
    .offset(0)
  }.map(Order(o, p, a)).list.apply()

上面的示例看起来与jOOQ代码非常相似,不同之处在于SELECT DSL似乎比jOOQ的刚性更高。 例如,如何在该WHERE子句中连接多个复杂谓词,或者根本不存在复杂谓词,现在还不是很明显。

但是,真正的好处是,它们利用Scala语言功能提供了一种非常流畅的动态SQL构造方法,如以下示例所示:

def findOrder(id: Long, accountRequired: Boolean) = 
withSQL {
  select
    .from[Order](Order as o)
    .innerJoin(Product as p).on(o.productId, p.id)
    .map { sql =>
      if (accountRequired) 
        sql.leftJoin(Account as a)
           .on(o.accountId, a.id)
      else 
        sql
    }.where.eq(o.id, 13)
  }.map { rs =>
    if (accountRequired) 
      Order(o, p, a)(rs) 
    else 
      Order(o, p)(rs)
  }.single.apply()

根据我们对事物的理解,在SQL语句中间(在innerJoinwhere之间)调用的map方法可以使用允许在需要时附加leftJoin的lambda表达式来转换中间DSL状态。 显然,这也可以通过将中间DSL状态分配给局部变量来以更程序化的方式完成。

需要SQL查询DSL

过去,我们已经在博客中介绍了许多类似的SQL查询DSL。 它们不断出现在各种API中的事实并非偶然。 SQL是一种非常类型安全和可组合的语言,很难通过基于字符串的API(例如JDBC,ODBC等)动态使用。

在Java或Scala等宿主语言中使用类型安全的内部特定于域的语言模型SQL带来了很大的优势。 但是,如果没有以完全可预见的方式精心设计DSL,则缺点可能很快就会显现出来。 以下面的ScalikeJDBC QueryDSL示例为例:

val ids = withSQL {
  select(o.result.id).from(Order as o)
    .where(sqls.toAndConditionOpt(
      productId.map(id => sqls.eq(o.productId, id)),
      accountId.map(id => sqls.eq(o.accountId, id))
    ))
    .orderBy(o.id)
}.map(_.int(1)).list.apply()

这个toAndConditionOpt方法确实是出乎意料的,并没有遵循最小惊讶原则

这就是为什么jOOQ的API设计基于紧密模仿SQL本身的正式BNF的原因。 在这里阅读更多有关它的信息

翻译自: https://www.javacodegeeks.com/2014/03/a-sql-query-dsl-for-scala-by-scalikejdbc.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值