Groovy 1.8 :: LINQ Applied



2011年8月31日更新
Guillaume Laforge几乎做到了:
http://gaelyk.appspot.com/tutorial/app-engine-shortcuts#query

看起来他正在做AST转换以实现:

alias as Entity

位。很酷的东西,Groovy 1.8+AST transform=LINQ风格的JVM查询。据我所见,GL的解决方案需要更多的工作来实现完整的查询功能(如子查询、使用(字段)语法连接等),但对于他的Gaelyk项目来说显然没有必要。

编辑

作为实现纯LINQ语法的一种变通方法,我决定定义别名。这不是什么大不了的事,并且消除了一个可能需要复杂AST转换才能实现的主要障碍

所以,不是:

from   c as Composite
join   t as Teams
...

我现在定义别名(注意:需要强制转换才能自动完成字段):

def(Teams t,Composite c,Schools s) = [Teams.new(),Composite.new(),Schools.new()]

并使用from、join等的映射语法

from    c:Composite
join    t:Teams
...

要解决问题#2(请参阅下面的原文),请将实例级别的getProperty方法添加到每个pogo别名中(其范围仅限于调用它的ORM闭包,nice)。我们只是在构建sql语句时返回字符串属性名称。

[t,c,s].each{Object o-> o.metaClass.getProperty = { String k-> k } }

取得"良好"进展;-)

现在要弄清楚如何处理"=",这很棘手,因为set属性是无效的。可能需要使用eq、neq、gt等,但更喜欢文字符号,这更接近sql的可读性。

如果有兴趣的话,LINQ在幕后做了很多工作。Jon Skeet(称赞他的名字)有一个很好的SO回复:LINQ内部是如何工作的?

原件

一直在查看LINQ,印象深刻。

// LINQ example
var games =
    from t in Teams
    from g in t.Games
    where g.gameID = 212
    select new { g.gameDate,g.gameTime };

// Seeking Groovy Nirvana
latest { Integer teamID->
    from   c as Composite
    join   t as Teams
    join   s as Schools on ( schoolID = {
                     from   Teams
                     where  t.schoolID = s.schoolID } )
    where   t.teamID = "$teamID"
    select  c.location, c.gameType, s.schoolName
    group   c.gameID
    order   c.gameDate, c.gameTime
}

所提出的Groovy版本编译得很好,如果我用它们对应的POGO定义别名c,t,s,我就会得到字段上的强类型IDE auocomplete,很好。然而,在LINQ附近,除了查询本身之外,没有(可见的)变量定义,完全是自包含的,并且是强类型的,哇。

好吧,那么它可以在Groovy中完成吗?我想(希望)是的,但我在两个问题上挂断了电话:

1) 如何隐式填充别名变量而不进行定义?目前,我正在重写String上的asType(),因此在"从c作为复合"中,c被强制转换为复合。很好,但IDE"认为"在闭包范围内未定义的c是一个字符串,因此在POGO字段上没有自动完成-(

2) 由于#1没有解决,我按照上面的定义别名,这样我就可以自动完成了。很好,被黑客入侵(与LINQ相比),但能做到。这里的问题是,在"select c.location,c.gameType…"中,我希望不计算字段,而只是将"c.location"返回给ORM select方法,而不是null(这是它的默认值)。getProperty()应该在这里工作,但我需要它只适用于从ORM范围调用的pogo字段(例如,ORM字段特定的方法,如select、order、group等)。这里有点迷失了方向,也许有一种方法可以注释ORM方法,或者只通过ORM方法调用"特殊"pogogetProperty(这是上面涅盘查询中闭包的委托)。

应该指出的是,我并不想为Groovy创建一个全面的LINQ,但我希望看到LINQ的一个子集能够实现。

Guillaume使用AST转换的最大原因之一是"="的问题。即使像在Groovy中通常使用==进行比较,从为其调用的compareTo方法中,也无法区分==、!=、<=,>=<,>。在稍后讨论的Groovy版本中,有两种可能的路径。一种是为每种比较使用不同的方法,另一种是存储可以在运行时访问的最小AST。这是朝着C#的方向发展的,是一个非常强大的工具。问题更多的是如何有效地做到这一点。

相关内容

  • 没有找到相关文章

最新更新