How to retrieve the latest created db entry? - grails

I have the following class and need to manually increment the nextId field.
class SomeIdClass {
Family family
Integer nextId = 0
long timeCreated = new Date().time }
So far I've been trying to retrieve and the latest db entry to increment it and I'm just not having any luck with that. Or am I just going about it in a totally wrong manner?
Thaks
ps: this is what I tried but get a list of Package.SomeId objects
def si = SomeId.executeQuery(" from SomeId where nextId = (select max( nextId ) from SomeId) ")

My two cents for return the last row in Grails:
DomainClass.find("from DomainClass order by id desc")

You can simply get the last saved value this way:
//works only if the primary key 'id' is non-composite
def lastEntry = SomeIdClass.last(sort: 'id')
//alternative method which will work even for composite primary key
def entryList= SomeIdClass.findAll{[sort:'id',order:'asc']}.last()

You can do this:
def maxNextId = DomainClass.executeQuery("select max(nextId) from DomainClass")[0]
Without seeing the whole context, it's hard to tell what you're doing, but as an aside, this looks pretty questionable. This method to assign ids to domain objects is probably the wrong way to go about it. But in any case, what if a new object gets inserted into the database with a greater nextId in between the time you do the query and use the value?

What about replacing
long timeCreated = new Date().time
with
Date dateCreated
which grails automatically populates, to your domain class?
Then you could do something along the lines of
SomeIdClass.listOrderByDateCreated(max: 1, order: "desc")
Also, you do know that by default grails gives every domain object an id that auto-increments right?

Why not using a sequence? You can use a sequence that is global to all your domain classes or you can define a specific sequence for that domain. You can do something like this:
static mapping = {
id generator: 'sequence', params: [sequence: 'some_name_sequence']
}
..and if for some reason you still need to have a nextId, you can create a get method that returns the value of id, something like:
def getNextId() {
return id
}
If you do this then you would need to define nextId as a transient value.
This of course assuming you don't need id and nextId to be different.

From http://www.hsqldb.org/doc/guide/ch09.html#create_table-section
The last inserted value into an identity column for a connection is available using the function IDENTITY(), for example (where Id is the identity column):
INSERT INTO Test (Id, Name) VALUES (NULL,'Test');
CALL IDENTITY();
So, assuming you're using HSQL, you may be able to do:
SomeIdClass.executeQuery("call identity();")
to get the last inserted ID and add to it. MySQL has its own similar feature if HSQL is not the correct route.
This answer is NOT TESTED.

// retrieve the last person
def p = Person.last()
//get the current id
def currentId = p.id
//increment the id manually
def nextId = currentId+1
You can also use the generator in the domain class mappings.
static mapping = {
table 'PERSON'
id generator: 'increment'
version false
}

Ummh, try
SomeIdClass.where {
// any criteria - or none
}.max('nextId').list()[0]
But of course you should be using a sequence generator for ids.

Related

How to bulid a criteria query to get the data of my domain

I know that have to be really easy, but I'm new in grails and I don't find any clear answer. That I want to do is read and get with a criteria query the data that I have in my domain do a search for each parameter.
This is my domain Person:
String name
String surname
String address
String village
String country
This is that I'm trying to do:
def getData = Person.createCriteria()
I can see in the log that I have an object (com.mypackagename.Person: 1.), but not the data that I have in the database. example (myname, mysurname, myaddress, myvillage, mycountry)
I only have one row of data in my database and I want to get the data of every column and do a search for each parameter
Thanks in advance.
Let me show you the code first, then I'll explain it:
class SomeController {
def search() {
def people = Person.withCriteria {
params
.findAll { name, value -> name in ['name', 'surname', 'address', 'village', 'country'] }
.each { name, value -> eq(name, value) }
}
// Do as you please with 'people'; a list of Person instances.
}
}
Ok, so let's say you have a controller method (ex. search()) which receives the query parameters from the user. The parameters would be in the params Map. For example, if the user searches for the name John and the country USA, params would look like this: [name: 'John', country: 'USA']. Even though there are other search parameters available, we won't use them because the user did not specify them.
Within the criteria query, first search for the param key/value pairs which you care about; the searchable properties of Person. Then, for each of those pairs call eq(String propertyName, Object value) to set up the query criteria (the WHERE clause).
Using the example data, Hibernate will generate SQL that looks something like this:
SELECT name, surname, address, village, country
FROM person
WHERE name = 'john' AND country = 'USA'
And that's it!
Note: You will see the same output in the log (ex. com.mypackagename.Person: 1). That's because you're logging personInstance.toString(). So if you want the log entry to look differently, you'll need to override Person.toString() A very easy way to remedy this is to use Groovy's #ToString AST.
For more about creating criteria queries, take a look at my series of articles. I cover criteria queries using SQL terminology.
Try to use:
def persons = Person.createCriteria().list{}
or if you want just one result:
def persons = Person.createCriteria().list {
maxResults 1
}
Moreover please read about using Criteria and Querying with GORM

Rails/Mongoid best way to save sortable ordered list

I've got a sortable list of players pulled from my db. Users can rank them in order of their preference.
What's the best way to store that order in the db associated with each player's preference and retrieve player stats back in that same order?
Right now I'm retrieving by #playersdraftlist = #draftlist.map { |id| Player.find(id) }, but this hits the db many times.
So, currently, I have a User model and a Draft model. The draft only has an associated user_id.
1) Would it be better to just store the draftees as a user field instead of a separate model?
2) Is there a better way to store a list like this when I need to retain dupes and order?
Structure:
PlayerDraft model has an associated user_id:
draftees: [
"52f4fd9f52e39bc0c15674ea", #Peyton
"52f4fd9f52e39bc0c15674eb", #Tom
"52f4fd9f52e39bc0c15674ea" #Peyton
],
user_id: "52f581096b657612fe020000"
#draftees = Draft.find(user_id = current_user._id).first.draftees will return the draftees array.
Calling Player.find(#draftees) will remove the duplicates and order by _id.
Edit
Here is my poor solution:
def index
#players = Player.all
if current_user.draft_list.draftees == [""]
#playersdraftlist = ""
else
# Get all picks for current user
#picks = current_user.draft_list.draftees
#draft = Player.find(#picks)
#playersdraftlist = #picks.map { |id| Player.find(id) }
end
end
The way to do this is to use the identity map in mongoid.
There are more details on this here: http://mongoid.org/en/mongoid/docs/identity_map.html
But the short and simple way to do this is in your mongoid.yml set the following property:
identity_map_enabled: true
Then search for the following: Player.find(#draftees)
And this will return your draftees in the order of the array that you passed in. One caveat is that it won't return duplicates so your #draftees array above if used would return only two values (the order is based on the first appearance of the id, so it will return the player with id "52f4fd9f52e39bc0c15674ea" first and then the player with id "52f4fd9f52e39bc0c15674eb"). So you will have to recreate the duplicates via some sort of abstraction.
Here is one possible way to do this, and it was inspired by a comment posted by #muistooshort below:
In your User class add the following function
def get_draftee_list
players = Player.find(self.draftees).each_with_object({}) { |p, h| h[p.id] = p }
return self.draftees.map { |id| players[Moped::BSON::ObjectId.from_string(id)] }
end
Note: This was tested on Mongoid 3
This should solve your problem since each call to raw_data.find(id) is searching the result set from your the initial query which is stored in memory and not making another query to the db

How to create a static class that represents what is in the database?

I have a table that looks like:
AccountType
ID Name Property1 Property2 Property3
On startup, I want to create a class that represents the database rows, that I can reference by both the ID and Name.
I want this to be a static representation (it will never change, if it does in the rare occasion, i can restart the application) because I will be referencing in my code and don't want to hit the db all the time.
I need it in the database because I need to join it with other tables also.
Can this be done?
Usage:
AccountType[1]
AccountType["PRO_PLAN"]
Definitely. Try this:
#config/initializers/constants_from_account.rb
ACCOUNT_TYPE = {}
AccountType.all.each do |account_type|
ACCOUNT_TYPE[account_type.name] = account_type
ACCOUNT_TYPE[account_type.id] = account_type
end
Then you can use ACCOUNT_TYPE[1] or ACCOUNT_TYPE["PRO_PLAN"] -- either the ID or the name -- to access your new hash of account types.

Grails GORM loading collection of objects issue

I'm trying to load a list of Evaluations in a class named Contributor but I'm missing something as I cannot get my test passing.
My test is creating and saving objects as expected because when I do Evaluations.list() and Contributor.list() and print the values I see the data I saved.
Furthermore, when I select an Evaluation and print the value of its 'contributor' property it appears to be correct.
However, when I select a Contributor and print the values of its 'evaluations' property it is null.
I assume my mapping is the problem?
class Contributor {
String name
static hasMany = [evals:Evaluation]
static mapping = {
id column: 'user_id'
evals joinTable:[name:'evaluation', column:'eval_id', key:'eval_user_id']
version false
}
}
class Evaluation {
Contributor contributor
String comment
static mapping = {
id column:'eval_id'
contributor column:'eval_user_id'
version false
}
}
Thanks.
You shouldn't assign evals like contributor.evals = [eval]. Rather invoke a dynamic method addTo*(): contributor.addToEvals(eval). This will create a Hibernate collection for evals which will be persisted later.
The first one didn't work because Grails doesn't assign other end of association when you assign eval.contributor, i.e. it doesn't call contributor.addToEvals(eval). I have no idea why - there must be some implementation reason.
So contributor remains with the same empty evals in Hibernate cache. If it falls out of cache and you re-read it, it will have evals filled, because the association is mapped only on Eval table's foreign key.
Empty evals are null - it's another Hibernate feature: when a collection is empty, it can be null. Just know it.
Here's an good short post explaining some Hibernate internals: http://blog.xebia.com/2008/03/advanced-hibernate-proxy-pitfalls/
Ahh I've sussed it. The problem is the way I was saving the objects.
The following does not work:
def contributor = new Contributor([name:'Homer']).save(failOnError:true)
def eval = new Evaluation([contributor:contributor, comment:'Must read article']).save(failOnError:true)
This
def contributor = new Contributor([name:'Homer']).save(failOnError:true)
def eval = new Evaluation([contributor:contributor, comment:'a comment']).save(failOnError:true)
contributor.evals = [eval]
contributor.save(failOnError:true)
Or this, does work:
def contributor = new Contributor([name:'Homer'])
def eval = new Evaluation([contributor:contributor, comment:'a comment'])
contributor.evals = [eval]
contributor.save(failOnError:true)
Not sure I fully understand why the top save method doesn't work when selecting data since the id of the contributor is saved on the evaluation.

grails findAll tag

How to use "SELECT id, name, part, description FROM user " in grails findAll tag.
I tried
User.findAll("SELECT id, name, part, description FROM user")
instead using
User.findAll("FROM user")
But shows errors.
What is the tag?
finadAll() returns a Collection of domain objects, so enumerating columns to select does not make sense; the queries it understands are not real SQL, and consist basically only of WHERE clauses. Since you don't seem to want to constrain the result set, this is probably all you need:
User.findAll()
It will return a collection of all User objects. If you need constraints, the syntax ist
User.findAll("from User as u where u.id=?", [userId])
Or, even simpler, you can use a dynamic finder:
User.findAllById(userId);
If you want to run report-style queries like this, use the executeQuery method:
def rows = User.executeQuery("SELECT id, name, part, description FROM User")
The return value will be a List of Object[] where each element in the object array is the type of the column, i.e. the 1st element will be a long, 2nd a String, etc.
Note that User has to be capitalized since you're referring to the Hibernate entity - this isn't a SQL query, it's HQL.
If you want to query for only certain fields, you can use a criteria query with a projection.
Example:
def userProperties = User.withCriteria {
projections {
property('id')
property('name')
property('part')
property('description')
}
}
This query will return an array of Strings (or whatever the database column type is mapped to) for each matching row, instead of a domain object.
It will return an ArrayList of objects you only have to access that objects values. For example:
def result = Code.findAll("from Code as c where c.user_code=?",[pass])
result[0].user_code
Where my Code class is something like this:
class Code {
String user_code
boolean flg_active
static constraints = {
user_code nullable:true, blank:true, size:0..Text.MID
flg_active nullable:true, blank:true, default:1
}
}

Resources