Home Grails/GORM: How to implement custom EntityPersister?
Reply: 0

Grails/GORM: How to implement custom EntityPersister?

David Leaman
1#
David Leaman Published in 2018-01-10 15:09:03Z

One problem I am having is that Hibernate 4.3.10 doesn't support nullable components of composite unique indices. This is a problem because for one of my (legacy) tables the ID is generated by a table trigger on insert, so I need to use generator: "select" in order to persist properly, but the only available unique index includes nullable fields. So when I insert a new record and Hibernate looks for the record I just inserted, null values cause the query to return no results. I found the culprit, here:

org.hibernate.persister.entity.AbstractEntityPersister

3044  public String getSelectByUniqueKeyString(String propertyName) {
3045    return new SimpleSelect( getFactory().getDialect() )
3046      .setTableName( getTableName(0) )
3047      .addColumns( getKeyColumns(0) )
3048      .addCondition( getPropertyColumnNames(propertyName), "=?" )
3049      .toStatementString();
3050  }

On line 3048 there is nothing null-safe happening, so the resultant query winds up looking something like:

SELECT ID FROM TABLENAME WHERE SOME_COLUMN = NULL

I think I can resolve this by writing my own persister extending GroovyAwareSingleTableEntityPersister, which is the persister that is currently used for this class. I think I can make it nullsafe by replacing that errant line 3048 with something like:

for (String columnName : getPropertyColumnNames(propertyName))
  select.addCondition( "decode(" + columnName + ", ?, 1, 0)" , "=1" );

However, I'm having difficulty figuring out how to plug it in. I found this thread response on Nabble that seems to do exactly what I want, but so far I can't figure out how to get a reference to a class I can call setEntityPersisterClass() on. Right now I'm working with the following:

import grails.util.Holders
import org.codehaus.groovy.grails.commons.GrailsDomainClass
import org.hibernate.mapping.RootClass

class MyBootStrap {
  def init = {
    println "Starting Persister substitution..."

    Holders.grailsApplication.getArtefacts("Domain").each { GrailsDomainClass gdc ->
      println "class: " + gdc.getName() + " | root: " + (gdcinstanceof RootClass)
      if (gdc instanceof RootClass)
      {
        RootClass root = (RootClass) gdc;
        println "class: " + root.getClassName() + " | persister: " + root.getEntityPersisterClass().name
        if ("FooClass".equals(root.getClassName()))
        {
          root.setEntityPersisterClass(MyNullSafePersister.class);
        }
      }
    }
  }
}

This correctly finds all the domain classes, but none is an instance of PersistentClass or RootClass, and none of them implements setEntityPersisterClass(). I suspect the use of these classes may have changed since 2010, and replaced with a different mechanism, but so far I haven't been able to figure out what.

So how can I set a custom EntityPersister for a class in Grails 2.5.6 and Hibernate 4.3.10?

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.30829 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO