7

I'm looking a way to bind Type for specific entity fields during entity manager configuration phase. I need it to be able to apply extra "rules" to target entity field using external source without entity class changes.

So basically I'm trying to avoid hardcode @Type annotation way as below:

@Type(type = foo.package.MyType, parameters = {
    @Parameter(name = "fooProperty", value = "fooValue")
})
private String someField;

Instead I would like to set Type for someField while building model programmatically.

user9440008
  • 572
  • 1
  • 9
  • 21

1 Answers1

3

Here's one way I've seen before. It is a little low-level, so I suspect there is a cleaner way to do this.

This uses a custom Persister in Hibernate to allow us to substitute the type while the SessionFactory ( EntityManagerFactory ) is being created.

First, the @Persister annotation is used to declare the custom Persister :

@Entity
@Persister(impl = MyPersister.class)
public class EntityWithPersister {

    private String someField;

Then normally the custom persister should extend SingleTableEntityPersister in Hibernate. If the entity is using a different @Inheritance(strategy), then it may need to extend JoinedSubclassEntityPersister or UnionSubclassEntityPersister instead.

This offers the chance to change a type at the point of construction, for example:

public class MyPersister extends SingleTableEntityPersister {

    public MyPersister(PersistentClass persistentClass,
            EntityDataAccess cacheAccessStrategy,
            NaturalIdDataAccess naturalIdRegionAccessStrategy,
            PersisterCreationContext creationContext)
            throws HibernateException {
        super(modify(persistentClass), cacheAccessStrategy,
                naturalIdRegionAccessStrategy, creationContext);
    }

    private static PersistentClass modify(PersistentClass persistentClass) {
        SimpleValue value = (SimpleValue) persistentClass
                .getProperty("someField").getValue();
        value.setTypeName(MyType.class.getName());
        return persistentClass;
    }
}

If you need to access more of the context you are in, creationContext.getSessionFactory() is probably a good starting point.

df778899
  • 10,703
  • 1
  • 24
  • 36
  • 1
    Didn't know such an approach, thanks for sharing. However, while it improves the current situation of mine I still need to annotate each entity by hand with correct persister (for different inheritance strategy support). – user9440008 Apr 29 '19 at 10:54
  • 1
    I was able to override types w/o changing entity at all using this approach plus registering own PersisterClassResolver. – user9440008 May 05 '19 at 14:05