Prevent duplicate entry for save smartly in grails - grails

I have a domain named thana where I put all the thanaName. But I don't want to save any duplicate name. There may be a lot of way for doing this but which will be much smarter I don't know. Can anyone please help me on this. any example or source code will do the work perfectly. thanks in advance for watching the question.

This sounds like the prefect use case for the unique constraint.
class MyDomain {
String name
OtherDomain related
static constraints = {
name unique: ['related'] // each instance must have a unique name per related
}
}
Edit
Updated based on question in comment. The above will ensure that name is unique for each related. So, for example if MyDomain A has a related instance id of 1 and a name of "Test" no ohter instance of MyDomain with the same related instance can have the name of "Test". However, MyDomain B which has a rleated instance id of 2 can have a name of "Test" since the unique is per "related" in the above example.

Related

Is it possible to save a specific id for a grails domain object?

I am in the process of trying to copy the properties of one domain object to another similar domain object (Basically moving retired data from an archive collection to an active one). However, when I try to save with a manually inputed id the save will not actually put anything into the collection.
def item = new Item(style: "631459")
item.id = new ObjectId("537da62d770359c2fb4668e2")
item.save(flush: true, validate: false, failOnError:true)
The failOnError does not throw an exception and it seems like the save works correctly. Also if I println on the item.save it will return the correct id. Am I wrong in thinking that you can put a specific id on a domain object?
You can set the id generator as 'assigned' so then you can put the value that you want and is going to be saved with that value.
class Item {
...
static mapping = {
id generator:'assigned'
}
}
The identifier id is a somewhat sensitive name to use. If you check your dbconsole, you will find that GORM has provided one for you even without asking. When you use that name for yourself, confusion happens. Grails will respect you with the println stuff, but GORM has the last word on how id gets initialized and stored, and it is not listening to you then.
You can rename the id to something else like you see in this post and maybe then you can use the name id for yourself. Otherwise, I suggest leaving id to GORM, and have your own identifier for your old keys. You won't have problems retrieving data anyway and there won't be performance issues.

Grails save() method bug

For example I have entity person saved in db with the name John and id 1 then:
def person = Person.get(1)
person.name = 'Maria'
person.save()
//after that name still will be John
//but if I save one more time than name be Maria
Addition information is that my domain have inside service, and method that work with this service.
I don't now in what is a problem, maybe somebody had already this situation.
It's not flushed at this moment, changes kept in memory for a while. If you need to force Grails to update DB exactly at this moment, add flush: true parameter:
person.save(flush: true)

Removing multiple items from a Grails One to Many relationship

I'm creating an application using Grails 2.2.4 and Java 7 (these are constraints I cannot change) and I run into an odd behavior when trying to delete multiple entries in a Many-To-Many hasMany Set.
I have a class named Sport that contains the following:
Class Sport{
String name
static hasMany=[category:Category]
static belongsTo = [Category]
}
And another one named Category:
Class Category{
String name
static hasMany=[sports:Sport]
}
Now when in my CategoryController I try to delete multiple Sport instances from sports, my code compiles and runs without errors, but for reason only one of the selected instances is actually deleted.
If I get a Sport list and a Category id from a form and try to run the following code on every objet in the list:
def categoryInstance = Category.get(idCategory)
def sportInstance = Sport.get(idSport)
if(sportInstance!=null){
categoryInstance.removeFromSports(sportInstance)
}
categoryInstance.save()
Only the last instance is deleted.
If I run
def categoryInstance = Category.get(idCategory)
def sportInstance = Sport.get(idSport)
if(sportInstance!=null){
categoryInstance.removeFromSports(sportInstance)
categoryInstance.save()
}
Only the first one is deleted.
Note that this code is run from within a for loop over the params.sport.toList() list.
My guess is that this is either due to the fact that my sports Set is somehow "changed" after the first deletion and therefore Hibernate can't find the next instance, or that my save method commits the first change then "forgets" the next.
Any advice on how I can delete more than one instance at a time?
A workaround is to wrap the code for deleting a single association in a block of withNewSession + withNewTransaction
Sport.withNewSession {
Sport.withNewTransaction {
//delete 1 association here
}
}
It's not very elegant but works. Beware of a potential performance impact, as this will likely have many database roundtrips.
I don't know why this problem occurs, and googling didn't help either.
Another solution = workaround is to explicitly map the relationship as SportCategory, which you can then delete like any other object with SportCategory.delete().

GORM mapping: make an index unique

I'm feeling a little slow today. I'm trying to do something that I think is very simple. I have a Domain class with a property called 'name'. I want 'name' to have an index, and I want the index to require that the 'name' is unique. I've set the unique constraint and tried creating an index. I can't make sense out of the Gorm docs as to how I add the unique attribute to the index. Here's some code:
class Project {
String name
static hasMany = [things:Things]
static mapping = {
name index:'name_idx'
}
static constraints = {
name(unique:true)
}
}
All is well with the above, except when do "show indexes from project" in mysql it shows my name key as not unique. I know the problem is that I am not specifying unique in the mapping, but quite frankly the docs for gorm are making my head hurt. I see all kinds of stuff about columns, but I can't find a single example anywhere on the web that shows what I want to do. I don't need complex mappings or compound keys, I just want to know the syntax to add the unique attribute to the mapping declaration above. Any advice welcome.
I also did a grails export-schema and see the following:
create index name_idx on project (name);
Nothing in that to indicate this index requires unique values
A related followup question would be once I succeed in making that index unique, what type of error should I expect when I go to save a Project instance and the name is not unique? Is there a specific exception thrown? I realize that even if I check that a given 'name' is unique there's still a possibility that by the time I save it there may be a row with that name.
I'm quite sure the syntax to do what I want is simple but I just can't find a simple example to educate myself with. I've been to this page but it doesn't explain HOW the uniqueness is enforced. I'd like to enforce it at the name index level.
The indexColumn allows additional options to be configured. This may be what you're looking for.
static mapping = {
name indexColumn:[name:'name_idx', unique:true]
}
Grails Documentation for indexColumn
If you put only the unique constraint the GORM send DDL to create an unique index on database.
static constraints = {
name nullable: false, unique: true
}

db4o - unique constraints on a group of fields

I would like to have unique constraints operate on more than 1 field for several entities. How can I achieve this with db4o?
Thanks,
Walter
Currently db4o doesn't support the UniqueConstrain on multiple fields. You can set unique-constrains only field by field, but not combine them.
#Ladlestein Well the intention is good, but it doesn't work. db4o manageds objects by it referencial identity. When you apply the unique-constrain on the Foo.name, you ensure that the reference is unique. So no other object can have the same reference to a name object. But you're not interested that the reference is unique, but you want to have a unique content of the names.
Sounds like a composite key. Can you create a new class that contains the key-constituting fields, and use a member variable with that type in place of the key-constituting fields in your original class?
i.e. where you had
class Foo {
String given_name;
String family_name;
}
instead use
class Name {
String given_name;
String family_name;
}
class Foo {
Name name;
}
and make Foo.name the unique field?

Resources