Scala的SQL DSL

Tim*_*per 9 dsl scala querydsl

我正在努力为Scala创建一个SQL DSL.DSL是Querydsl的扩展,Querydsl是一种流行的Java查询抽象层.

我现在正在努力解决以下非常简单的表达方式

user.firstName == "Bob" || user.firstName == "Ann"
Run Code Online (Sandbox Code Playgroud)

由于Querydsl已经支持可以在这里使用的表达式模型,因此我决定提供从Proxy对象到Querydsl表达式的转换.为了使用代理,我创建了一个这样的实例

import com.mysema.query.alias.Alias._

var user = alias(classOf[User])
Run Code Online (Sandbox Code Playgroud)

通过以下隐式转换,我可以将代理实例和代理属性调用链转换为Querydsl表达式

import com.mysema.query.alias.Alias._
import com.mysema.query.types.expr._
import com.mysema.query.types.path._

object Conversions {        
    def not(b: EBoolean): EBoolean = b.not()        
    implicit def booleanPath(b: Boolean): PBoolean = $(b);        
    implicit def stringPath(s: String): PString = $(s);        
    implicit def datePath(d: java.sql.Date): PDate[java.sql.Date] = $(d);        
    implicit def dateTimePath(d: java.util.Date): PDateTime[java.util.Date] = $(d);        
    implicit def timePath(t: java.sql.Time): PTime[java.sql.Time] = $(t);            
    implicit def comparablePath(c: Comparable[_]): PComparable[_] = $(c);        
    implicit def simplePath(s: Object): PSimple[_] = $(s);        
}
Run Code Online (Sandbox Code Playgroud)

现在我可以构造这样的表达式

import com.mysema.query.alias.Alias._
import com.mysema.query.scala.Conversions._

var user = alias(classOf[User])
var predicate = (user.firstName like "Bob") or (user.firstName like "Ann")
Run Code Online (Sandbox Code Playgroud)

我正在努力解决以下问题.

eq并且ne已作为Scala中的方法提供,因此在使用它们时不会触发转换

该问题可以概括如下.当使用Scala类型中已有的方法名称(如eq,ne,startsWith等)时,需要使用某种转义来触发隐式转换.

我正在考虑以下问题

大写

var predicate = (user.firstName LIKE "Bob") OR (user.firstName LIKE "Ann")
Run Code Online (Sandbox Code Playgroud)

这就是Circumflex ORM中的方法,这是一个非常强大的Scala ORM框架,具有类似的DSL目标.但是这种方法与查询关键字(select,from,where等)不一致,后者在Querydsl中是小写的.

一些前缀

var predicate = (user.firstName :like "Bob") :or (user.firstName :like "Ann")
Run Code Online (Sandbox Code Playgroud)

谓词用法的上下文就是这样的

var user = alias(classOf[User])

query().from(user)
    .where( 
      (user.firstName like "Bob") or (user.firstName like "Ann"))
    .orderBy(user.firstName asc)
    .list(user);
Run Code Online (Sandbox Code Playgroud)

对于Scala,您是否看到更好的选项或不同的SQL DSL构造方法?

所以这个问题基本归结为两个案例

  • 当使用超类中存在的方法时,是否可以触发隐式类型转换(例如eq)

  • 如果它是不可能的,这将是最Scalaesque语法使用像方法eq,ne.

编辑

我们通过使用别名实例和基于$ -prefix的转义语法在Querydsl中获得了Scala支持.这是关于结果的博客文章:http://blog.mysema.com/2010/09/querying-with-scala.html

Mat*_*ell 4

在 Scala Days 上有一个非常好的演讲:Christoph Wulf 在 Scala 中嵌入类型安全的 SQL。

请观看此处的视频:Christoph Wulf 嵌入 Scala 中的类型安全 SQL