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.

1
  • could you please explain more Commented Apr 26, 2019 at 7:53

1 Answer 1

3
+50

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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).
I was able to override types w/o changing entity at all using this approach plus registering own PersisterClassResolver.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.