How to create a custom Grails query - grails

I'm new to Grails and I've some troubles with queries. I got two domain classes like this:
class Cliente {
String nombre
String cuit
String localidad
String establecimiento
static hasMany = [facturas: Factura]
}
class Factura {
String Proveedor
int sucursal
String numero
String letraFactura
Cliente cliente
Date fecha
String tipo
}
I want to list all elements in facturas with client name:
Result expected:
Proveedor|sucursal|numero|cliente_nombre|fecha
I've tried some different ways but always get the cliente_id not cliente_nombre.

I think I know what you are asking: given a client name, return a list of factura's, with the stipulation that the list of fields should contain the client name rather than the client id.
import org.hibernate.criterion.CriteriaSpecification
// given a client name
def clientNameToSearch = 'some name'
def crit = Factura.createCriteria()
def results = crit.list() {
createAlias('cliente', 'cli')
eq('cli.nombre', clientNameToSearch)
// optional transformer to output a map rather than a list
resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
projections {
property('Proveedor', 'Proveedor')
property('sucursal', 'sucursal')
property('numero', 'numero')
property('cli.nombre', 'clienteNombre')
property('fecha', 'fecha')
}
}
results would then contain a list of maps, with each map having this structure:
[
Proveedor: ...,
sucursal: ...,
numero: ...,
clienteNombre: ...,
fecha: ...
]

Related

accessing object values using variable as a key

I'm trying to access a class value by using a variable previously defined in dart, but I keep getting the error the operator [] isn't defined for the class
In Javascript I would access an object value using a variable like this:
let movie = {
movieTitle : 'Toy Story',
actor: 'Tom Hanks'
}
let actorName = 'actor';
console.log(movie[actorName]); // <- what I'm trying to replicate in dart
// expected output: Tom Hanks
Here is what I've tried and is throwing that error
class Movie {
String name;
String actor;
String producer;
}
void main() {
var movieTitle = new Movie();
movieTitle.name = 'Toy Story';
movieTitle.actor = 'Tom Hanks';
print(movieTitle.actor); <- prints out Tom Hanks as expected
var actorName = 'actor';
print(movieTitle[actorName]); <- throws error
}
I expect to be able to use a variable on the fly to access the value.
A trivial use case for me would be if I had a a list of Movie classes, where some actors and producers are null, I would like to filter on either non null actors or producer with a function like so:
List values = movieList.where((i) => i.actor != "null").toList(); // returns all Movies in movieList where the actor value isn't the string "null"
var actorIsNull = 'actor';
List values = movieList.where((i) => i[actorisNull] != "null").toList(); // throws error
You can createn a toMap() function in your Movie class and access properties using [] operator
class Movie {
String name;
String actor;
String producer;
Map<String, dynamic> toMap() {
return {
'name': name,
'actor' : actor,
'producer' : producer,
};
}
}
Now Movie class properties can be accessed as:
Movie movie = Movie();
movie.toMap()['name'];
You cannot access class members by a string containing their name. (Except with mirrors - outside the scope of this answer.)
You could remove the class altogether and just use a Map<String, String>.
Map<String, String> movie = {
'movieTitle': 'Toy Story',
'actor': 'Tom Hanks',
}
You could add some bool methods on the class.
bool hasNoActor() => actor == null;
...
List values = movieList.where((m) => !m.hasNoActor()).toList();
Or, you could pass a lambda to your mapper.
Movie movieTitle = Movie()
..name = 'Toy Story'
..actor = 'Tom Hanks';
Function hasActor = (Movie m) => m.actor != null;
List values = movieList.where(hasActor).toList();

Groovy: Dynamic nested properties [duplicate]

I am wondering if I can pass variable to be evaluated as String inside gstring evaluation.
simplest example will be some thing like
def var ='person.lName'
def value = "${var}"
println(value)
I am looking to get output the value of lastName in the person instance. As a last resort I can use reflection, but wondering there should be some thing simpler in groovy, that I am not aware of.
Can you try:
def var = Eval.me( 'new Date()' )
In place of the first line in your example.
The Eval class is documented here
edit
I am guessing (from your updated question) that you have a person variable, and then people are passing in a String like person.lName , and you want to return the lName property of that class?
Can you try something like this using GroovyShell?
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
GroovyShell shell = new GroovyShell( binding )
def result = shell.evaluate( commandString )
Or this, using direct string parsing and property access
// Assuming we have a Person class
class Person {
String fName
String lName
}
// And a variable 'person' stored in the binding of the script
person = new Person( fName:'tim', lName:'yates' )
// And given a command string to execute
def commandString = 'person.lName'
// Split the command string into a list based on '.', and inject starting with null
def result = commandString.split( /\./ ).inject( null ) { curr, prop ->
// if curr is null, then return the property from the binding
// Otherwise try to get the given property from the curr object
curr?."$prop" ?: binding[ prop ]
}

How to save addTo in order by given date/id?

I need some help on my API, when I'm on web, the order is saving correct, but when its on API, it goes all wrong:
def test = parseJSON.sort { a, b -> a.ID <=> b.ID } //or dateTime, will print the same
//order when I print each of them
[IDWeb:0, conductivity:0, ReportId:2, dissolvedOxygen:0, levelWater:1, ID:1, ph:0, redoxPotential:0, temperature:0]
[IDWeb:0, conductivity:0, ReportId:2, dissolvedOxygen:0, levelWater:0, ID:2, ph:0, redoxPotential:0, temperature:0]
[IDWeb:0, conductivity:0, ReportId:2, dissolvedOxygen:0, levelWater:0, ID:3, ph:0, redoxPotential:0, temperature:0]
[IDWeb:0, conductivity:0, ReportId:2, dissolvedOxygen:0, levelWater:4, ID:4, ph:0, redoxPotential:0, temperature:0]
test.each{
def sample = new SampleWater()
sample.levelWater = it.levelWater
sample.conductivity = it.conductivity
sample.dissolvedOxygen = it.dissolvedOxygen
sample.redoxPotential = it.redoxPotential
sample.ph = it.ph
sample.temperature = it.temperature
water.addToSamples(sample)
}
return water
My problem is that addTo is not saving in order. How can I solve this?
Make sure you have defined the type of samples as a List in your Water domain class so that we can maintain the insertion order:
class Water {
static hasMany = [samples: Sample]
List<Sample> samples = []
}
class Sample {
def levelWater
}
By default implementation of hasMany is of type Set which does not maintain the insertion order but is responsible for uniqueness.
Since, now you samples will be saved in the same order as they are inserted.
You have to specify with order you want to apply to the list of SampleWater in the "water" domain class.
i.e:
class BlogCategory {
static hasMany = [
entries : BlogEntry
]
static mapping = {
entries: sort:'dateCreated', order:'desc'
}
}
In this example BlogEntry will be ordered respect dateCreated.

GORM where query on an embedded object

I have domain classes A and B as follows:
class A {
String prop1
String prop2
B prop3
static embedded = ['prop3']
}
class B {
String prop4
String prop5
}
When I want to query like this:
def q = A.where { prop3.prop4 == 'bla' }
def list = q.list()
I get the following exception:
Cannot get property 'javaClass' on null object. Stacktrace follows:
on the "def q = A.where ..." line.
Any clue what's the problem? I've checked this:
http://grails.1312388.n4.nabble.com/GORM-embedded-object-issue-td1379137.html
but how to "just call them directly" is not quite clear to me. Any other way of querying the embedded objects in GORM?
I finally gave up on the where query and went with the DetachedCriteria approach. Gives me the same flexibility as the where queries, but works with embedded domain objects:
def criteria = new DetachedCriteria(A).build {
eq 'prop1', 'bla2'
}
criteria = criteria.build {
eq 'prop3.prop4', 'bla'
}
def list = criteria.list()
What do you get if you do (assuming B is in src/groovy)
def q = A.where { prop3 == new B(prop4: 'bla') }
def list = q.list()
Embedded components are persisted inside the main domain class (owner) itself. It can be accessed directly using any dynamic finder as you do directly on a domain object.
The above can also be represented in dynamic finders as:
A.findAllByProp3(new B(prop4: 'bla'))

Grails additional columns in table or list

I'm trying for several days to receive a list from my Data. The Domain looks like this:
class Alpha {
String a
String b
etc.
static hasMany = [beta:Beta]
}
class Beta {
String a
Integer foo
String status
static belongsTo = [alpha:Alpha]
static constraints = {
status(nullable:false, inList:["val1","val2","val3", "val4"])
}
}
I'd like to have in Alpha the sum of all Beta.foo and of all Beta.foo in a certain status. Best would be something like an additional row ( Integer sumVal1 ... ).
I tried named queries:
static namedQueries = {
erledigterProbeAufwend {
createAlias ('Beta', 'b')
eq ('b.status', 'val1')
projections {
groupProperty('b.alpha')
sum('b.foo', 'sumFooVal1')
}
}
}
But this just give me one sum at a time.
I'm looking forward to get some help on that.
Greetings
Bas
This could be calculated formula field, but with a subquery trick:
static mapping = {
betaCount formula: "(SELECT count(*) FROM Beta b WHERE b.alpha_id = id and b.status in('a', 'b'))"
}
Create transient variables in your Alpha class and populate them in an onLoad event.
class Alpha {
String a
String b
etc.
static transients = ["sumVal1",...]
static hasMany = [beta:Beta]
def onLoad = {
sumVal1 = ....
}
}

Resources