简体   繁体   中英

Validate instance of domain class is unique

I have a Grails application with a bunch of domain classes, some with many fields, some of which have a hasMany relationship with the domain class in question. For this particular application I only have one "constraint", that is that every instance of every domain class must be unique. I don't care if an arbitrary field has the same value across multiple instances of the same domain class, so long as each instance is made unique by the value of some other field in that domain class. So basically I want validation to take place at a domain class instance level instead of the domain class field level. Right now I am doing that by using the very groovy @EqualsAndHashCode annotation to generate my equals and hashCode methods, then calling equals in a custom validator on some arbitrary field of a domain class.

Two questions:

  1. Is there a more efficient way of validating a domain class is unique?
  2. If no, then is there a way I can call my custom validator code on the domain class instance itself instead of going through one of the fields of the domain class instance?
@groovy.transform.EqualsAndHashCode
class MyDomainClass {
    String some
    int arbitrary
    boolean field
    static constraints = {
        // The field I chose to validate on is irrelivant, I just need to run the validation code **somewhere**
        arbitrary validator: { val, obj ->
            return !MyDomainClass.getAll().contains(obj)
         }
    }
}

I should also add I'm looking for a generic (hopefully efficient) way to do this. I realize calling getAll() is very inefficient and instead calling some variant of find or performing an HQL query on the exact fields of each domain class would be much more efficient... it just takes a lot longer to write!

Examples

    assert MyDomainClass.getAll().isEmpty() // true

    def myDomainClass1 = new MyDomainClass( some: "foo", arbitrary: 1, field: true)
    assert MyDomainClass.getAll().contains(myDomainClass1); // false
    myDomainClass1.save(flush:true)

    def myDomainClass2 = new MyDomainClass( some: "bar", arbitrary: 1, field: true)
    assert MyDomainClass.getAll().contains(myDomainClass2); // false.  Even though this has the same `arbitrary` value as myDomianClass1, it has a different `some` value which makes it unique.
    myDomainClass2.save(flush:true)

    def myDomainClass3 = new MyDomainClass( some: "foo", arbitrary: 1, field: false)
    assert MyDomainClass.getAll().contains(myDomainClass3); // false.  Even though this has the same `some` value as myDomainClass1 and the same `arbitrary` value as myDomainClass1 and myDomainClass2, it has a different `field` value which makes it unique.
    myDomainClass3.save(flush:true)

This will ensure the combination of the 3 fields in the domain are unique. This also ensures the constraint is on the database level, instead of just application level.

class MyDomainClass {
    String some
    int arbitrary
    boolean field
    static constraints = {
        some(unique: ['arbitrary', 'field'])
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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