Search code examples
grailsgroovygrails-orm

Abstract domain classes in GORM: how to deal with static GORM methods


Currently struggling with this.

I was hoping to be able to use an abstract domain class to enable me to use some generic code to do some commonly performed operations.

My problem is that a lot of the GORM operations are static methods on the domain class, this makes it difficult. Was wondering if there were any non-static equivalents of these methods, e.g. "withTransaction" "findById" etc which I could use. Or if there is any "groovy magic" that I could use?

BTW, am using GORM outside of grails, so I don't think I have access to the "static transactional=true" service setting.

Any help would be appreciated.

abstract domain class:

@Entity
public abstract class Entity<K> {
    public abstract String toNiceString();
    public K id;

    public K getId(){
        return id;
    }

    public void setId(final K id){
        this.id = id;
    }
}

and an example concrete class:

@Entity
@EqualsAndHashCode
class Person extends Entity<String> {
    String name
    String summary
    LocalDate birthDate
    LocalDate deathDate
    String occupations

    ...
}

and some generic code whereby I was hoping to be able to reuse across some domain objects, but of course the T.xxxx() static methods won't work.

public abstract class AbstractParser<T extends Entity> {

    protected void parseAndSavePages(){

        //Do some parsing
        ...

        T.withTransaction {
            if(T.findEntityById(entity.id)){
                println "Already exists!";
            } else {
                entity.save(failOnError: true);
            }
        }
    }
}

Solution

  • As in Java, the answer is likely to involve passing a Class object to the AbstractParser constructor.

    public abstract class AbstractParser<T extends Entity> {
    
        protected Class<T> entityClass
    
        protected AbstractParser(Class<T> entityClass) {
            this.entityClass = entityClass
        }
    
        protected void parseAndSavePages(){
    
            //Do some parsing
            ...
    
            // Groovy treats instance method calls on a Class object as calls
            // to static methods of the corresponding class
            entityClass.withTransaction {
                if(entityClass.findEntityById(entity.id)){
                    println "Already exists!";
                } else {
                    entity.save(failOnError: true);
                }
            }
        }
    }
    
    class PersonParser extends AbstractParser<Person> {
        public PersonParser() {
            super(Person)
        }
    }