grails:将SQL转换为域类

grails:将SQL转换为域类,grails,groovy,Grails,Groovy,我正在开发一个GRAILS应用程序(我是GRAILS新手,从以前的开发人员那里继承了这个项目)。我正在慢慢地了解GRAILS是如何运行的,以及域类、hibernate等的使用。MySQL数据库托管在Amazon上,我们使用ElasticCache 你们当中有谁知道我如何将下面的SQL语句转换成域类和查询条件吗 if(params?.searchterm) { def searchTerms = params.searchterm.trim().split( ',' ) def

我正在开发一个GRAILS应用程序(我是GRAILS新手,从以前的开发人员那里继承了这个项目)。我正在慢慢地了解GRAILS是如何运行的,以及域类、hibernate等的使用。MySQL数据库托管在Amazon上,我们使用ElasticCache

你们当中有谁知道我如何将下面的SQL语句转换成域类和查询条件吗

if(params?.searchterm) {

    def searchTerms = params.searchterm.trim().split( ',' )
    def resultLimit = params.resultlimit?: 1000
    def addDomain = ''

    if (params?.domainname){
        addDomain = " and url like '%${params.domainname}%' "
    }

    def theSearchTermsSQL = ""

    /*
     *  create c.name rlike condition for each search term
     *
     */
    searchTerms.each{
        aSearchTerm -> 
            if( theSearchTermsSQL != '' ){
                theSearchTermsSQL += ' or '
            }
            theSearchTermsSQL += "cname rlike '[[:<:]]" + aSearchTerm.trim() +  "[[:>:]]'"
    }

    /*
     *  build query
     *
     */
    def getUrlsQuery = "select
        u.url as url,
        c.name as cname,
        t.weight as tweight
    from
       (category c, target t, url_meta_data u )
    where
       (" + theSearchTermsSQL + ")
    and 
        t.category_id = c.id
        and t.url_meta_data_id = u.id
        and u.ugc_flag != 1 " + addDomain + "
    order by tweight desc
    limit " + resultLimit.toLong()


    /* 
     *  run query
     *
     */
    Sql sqlInstance = new Sql( dataSource )

    def resultsList = sqlInstance.rows( getUrlsQuery )

}
域类

class Category {

    static hasMany = [targets: Target]

    static mapping = {
        cache  true
        cache usage: 'read-only'
        targetConditions cache : true
    }

    String name

    String source
}

class Target {

    static belongsTo = [urlMetaData: UrlMetaData, category: Category]
    static mapping = {
        cache true
        cache usage: 'read-only'
    }

    int weight

}

class UrlMetaData {

    String url

    String ugcFlag

    static hasMany = [targets: Target ]

    static mapping = { 
        cache true
        cache usage: 'read-only'
    }

    static transients = ['domainName']

    String getDomainName() {

        return HostnameHelper.getBaseDomain(url)
    }
}
基本上,url元数据中的url可以关联到许多类别。因此,从本质上讲,我试图实现的应该是一个相对基本的操作……返回搜索词“car”的所有url,它们的权重(即重要性)以及ugc_标志不是1的位置(即url不是用户生成的内容)。数据库中有10万多条记录,这些记录是从第三方提供商导入的。请注意,所有的URL都属于我的客户机-这里没有做任何不可靠的事情

请注意我在查询中使用的rlike-我最初使用的是ilike%searchterm%,但这将查找searchterm属于较大单词的类别,例如“caravan”-不幸的是,如果用户请求“cars”,rlike不会返回任何内容


我编辑了代码——正如Igor指出的“域名”最初包含的奇怪内容。这是一个传递的可选参数,允许用户仅筛选特定域(例如“example.com”)的URL

我将创建给定域对象的空列表, 在resultsList上循环,从每一行构造一个域对象,并将其添加到这些对象的列表中。然后将该列表从控制器返回到视图。这就是您要寻找的吗?

1)如果它是一个从头开发的Grails应用程序(而不是基于遗留数据库结构),那么您可能已经有了域类
Category
Target
UrlMetaData
(否则,您必须手动或使用db反向工程插件创建它们)

2) 我假设
Target
有一个字段
Category-Category
Category
有一个字段
urlmatadata-urlmatadata

3) 方法可能是,我将尝试概述您的特定案例的基本情况

4) 不确定域是什么意思-可能是一种代码气味,也可能是从客户端接受类似于的参数

5) 下面的代码根本没有经过测试——特别是我不确定嵌套条件内部的析取是如何工作的。但这可能是一个合适的起点;记录sql查询应有助于使其正常工作()

当显式编写时,
限制可能工作得更好

if (searchTerms) { 
    def r = Restrictions.disjunction() 
    for (st in searchTerms) {
        r.add(new LikeExpression('name', st.trim()))
    }
    instance.add(r) //'instance' is an injected property
}
干杯,

Igor Sinev

谢谢Igor!我编辑了原始帖子,以包含db表和一些虚拟数据。在代码中修复了域名的使用,并进一步解释了我试图最终实现的目标。我仍然不确定您是否已经有了像
Category
Target
这样的域类,或者您现在需要创建它们。如果您确实有域类,那么您能告诉我代码是否建议帮忙?(我认为基于您的数据从头开始构建一个测试应用程序对我来说是不现实的——无论如何它都是不准确的)谢谢vector。我很乐意在resultsList上进行循环,目前我正在将其发送到gsp视图,正如您所提到的。实际上,我从问题中的代码中删除了它,只是为了将我的问题集中在如何将sql转换为hibernate上。
def c = Target.createCriteria() //create criteria on Target
def resultsList = c.list(max: resultLimit.toLong()) { //list all matched entities up to resultLimit results
    category { //nested criteria for category
        //the following 'if' statement and its body is plain Groovy code rather than part of DSL that translates to Hibernate Criteria
        if (searchTerms) { //do the following only if searchTerms list is not empty
            or { // one of several conditions
                for (st in searchTerms) { // not a part of DSL - plain Groovy loop
                    rlike('name', st.trim())) //add a disjunction element
                }
            }
        }
        urlMetaData { //nested criteria for metadata
            ne('ugcFlag', 1) //ugcFlag not equal 1
        }
    }    
    order('weight', 'desc') //order by weight
}
if (searchTerms) { 
    def r = Restrictions.disjunction() 
    for (st in searchTerms) {
        r.add(new LikeExpression('name', st.trim()))
    }
    instance.add(r) //'instance' is an injected property
}