简体   繁体   English

如何在grails中调用域内部的服务方法?

[英]How to call a service method inside of the domain in grails?

I have to call one method of my controller from my domain. 我必须从域中调用控制器的一种方法。 I'm trying to find some answer but I don't find anything and I'm not sure if is possible. 我正在尝试找到一些答案,但是我什么也没找到,我不确定是否可能。 Sorry, if my question is wrong, but in the requeriments that I have I have to find a solution for this, because I have do it inside of the method beforeInsert() in my domain. 抱歉,如果我的问题是错误的,但是在我有要求时,我必须为此找到解决方案,因为我已经在域中的beforeInsert()方法中进行了此操作。

This is the error when I try to run the project: 当我尝试运行项目时,这是错误:

| | Error 2015-12-02 10:59:29,210 [localhost-startStop-1] ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session) Message: null id in com.xxxx entry (don't flush the Session after an exception occurs) 错误2015-12-02 10:59:29,210 [localhost-startStop-1]错误hibernate.AssertionFailure-发生断言失败(这可能表示Hibernate中的错误,但更可能是由于不安全地使用会话)消息: com.xxxx条目中的null id(发生异常后不要刷新Session)

Controller method: 控制器方式:

def calculate(Integer max){
        params.max = Math.min(max ?: 10, 100)
        def users= User.findAllByType(null)
        LicenceTypeService.calculate(users) //This call a service
        redirect(action: "list", params: params)
    }

In my Domain: 在我的域中:

protected void callCalculateWhencreateUser(){
        def users= User.find("from User order by id desc")
        LicenceTypeService.calculate(users) //This call a service
    }

def beforeInsert() {
        encodePassword()
        callCalculateWhencreateUser()
    }

In my Service: 在我的服务中:

def calculate(def users){

        //logic code

    }

The subject of your question is misleading: you say that you need to call a controller method from a domain, but what your code says is that you're trying to call a service method from both domain and controller. 您的问题的主题具有误导性:您说您需要从域中调用控制器方法,但是您的代码说的是您正试图从域和控制器中调用服务方法。

You can't call a controller method from a domain, is conceptually wrong, but also you need a request to call a controller and you don't have it in a domain. 您不能从域中调用控制器方法,这在概念上是错误的,但是您还需要一个请求来调用控制器,而您在域中没有该方法。

However, what you're trying to do is in fact the way to do it: leave the logic to the service and call it from controller and domain. 但是,实际上,您要尝试的方法是:将逻辑留给服务,然后从控制器和域中调用它。 But you're doing it wrong. 但是你做错了。

In the controller you need to declare the service, so spring will inject it into your controller, just like this: 在控制器中,您需要声明服务,因此spring会将其注入到控制器中,如下所示:

class MyController {
    def licenceTypeService

    def calculate(Integer max){
        params.max = Math.min(max ?: 10, 100)
        def users = User.findAllByType(null)
        licenceTypeService.calculate( users )
        redirect(action: "list", params: params)
    }
}

You can use the actual type in the declaration of the service property instead of def, but the important thing is that the property name is the "logical name" of the service: the class name but with the first letter in lower case. 您可以在服务属性的声明中使用实际类型而不是def,但重要的是,属性名称是服务的“逻辑名称”:类名,但首字母小写。 That way the property will get injected by spring. 这样,该属性将在春季注入。

You should change the variable "user" for "users", it makes you think that is a single user but the finder you use returns a list of users instead. 您应该将变量“ user”更改为“ users”,这使您认为这是一个单一用户,但是使用的查找程序将返回一个用户列表。

On the domain you have to do just a bit more of work. 在域上,您只需要做更多的工作。 You need to inject the service in the same way, but you need to add it to the "transients" list, so GORM will not try to create a field in the database for it or retrieve it from the database. 您需要以相同的方式注入服务,但是需要将其添加到“瞬态”列表中,因此GORM不会尝试在数据库中为其创建字段或从数据库中检索字段。

Like this: 像这样:

class MyDomain {

    def licenceTypeService

    static transients = [ "licenseTypeService" ]

    def beforeInsert() {
        encodePassword()
        licenceTypeService.calculate( this )
    }
}

And your service would be something like: 您的服务将类似于:

class LicenceTypeService {

    def calculate( User user ) {
        // perform some calculation
        // do not call user.save() since this will be invoked from beforeInsert
    }

    def calculate( List<User> users ) {
        // If this is performed on several users it should be 
        // done asynchronously
        users.each {
            calculate( it )
            it.save()
        }
    }
}

Hope that helps. 希望能有所帮助。

However, depending on what you do in the calculate method (for a single user) it can be a method of the User class (that's a more OO solution). 但是,根据您在calculate方法中所做的操作(对于单个用户),它可以是User类的方法(这是一种更OO的解决方案)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM