Reputation: 19
I'm working with a project using GORM, without any Grails at all, and I'm having problems when I try to do a findByX. For instance, when I try a
Country.findByName("Canada")
The project does not compile, and it gives me
Error:(80, 9) Groovyc: [Static type checking] - Cannot find matching method app.domain.location.Country#findByName(java.lang.String). Please check if the declared type is right and if the method exists.
Even though the field Name exists.
I'm, however, able to, in CountryService.groovy, define a findByName method this way:
@Where({ name == countryName })
static Country findByName(String countryName){
Country.findAll().first()
}
But I don't think that's a good practice at all.
To summarize, Is there a dependency, a configuration, or something whatsoever I need in order to do GORM queries like Domain.findByX()? Or is it impossible using GORM standalone?
Thanks in advance.
Upvotes: 1
Views: 846
Reputation: 14642
Your issue isn't that the GORM method doesn't exist (eventually); it's that it doesn't exist at compile-time, and you appear to be using @CompileStatic
(or have your project configured where that's the default).
From the Grails documentation (which talks about Gorm and CompileStatic): https://docs.grails.org/latest/guide/staticTypeCheckingAndCompilation.html
One limitation of using CompileStatic is that when you use it you give up access to the power and flexibility offered by dynamic dispatch. For example, in Grails you would not be able to invoke a GORM dynamic finder from a class that is marked with CompileStatic because the compiler cannot verify that the dynamic finder method exists, because it doesn’t exist at compile time.
If you want to use GORM dynamic finders, you will need to turn off @CompileStatic
for the method/class using those finders. So either remove the @CompileStatic
annotation, or add @CompileDynamic
Other relevant:
Upvotes: 1
Reputation: 55
Using a Data Service is definitely a good idea, though your example would be better written as an interface
rather than a class
, without an implementation or the @Where
annotation and without being static.
@Service(Country)
interface ICountryDataService {
Country findByName(String name)
}
The parameter to the method definition should have the same name as the field in the domain class. As long as the return value is not a collection it will return the first one that it finds.
The @Where
annotation is useful when the query gets more complicated:
@Service(Country)
interface ICountryDataService {
@Where({ name ==~ pattern })
List<Country> searchCountriesByPattern(String pattern)
Country findByName(String name)
}
Upvotes: 0