How to unify @GenericGenerator declaration for multiple entities using same custom id generator?

2.6k Views Asked by At

There are many entities in my project that utilize the same custom IdentifierGenerator for @Id generation using SpringDataJPA/Hibernate.

An example entity;

@Entity
@Table(name = "CHAIRS")
public class ChairEntity {

    @Id
    @GeneratedValue(generator = "myGenerator")
    @GenericGenerator(strategy = "a.b.jpa.generator.MyGenerator", name = "myGenerator")
    protected String id;

    // rest of the entity
}

But I do not want to repeat @GenericGenerator decleration for every id field of every entity. Is there no way to hide this annotation that contains an ugly hardcoded full class name inside?

post scriptum
I was previously utilizing @MappedSuperClass with a BaseEntity class containing id field, but due to some technical reasons I had to abandon utilizing such a superclass. Obviously that is the easiest solution to this question.

2

There are 2 best solutions below

0
On BEST ANSWER

Solution I came up with was a Java trick, all my entities are under a.b.jpa.entity, and my generator in a.b.jpa.generator, and since @GenericGenerator can be used on class directly, I created a package-info.java for a.b.jpa.entity package with the following contents;

@GenericGenerator(strategy = "a.b.jpa.generator.MyGenerator", name = MyGenerator.generatorName)
package a.b.jpa.entity;

import org.hibernate.annotations.GenericGenerator;
import a.b.jpa.generator.MyGenerator;

That annotates all classes under a.b.jpa.entity with the @GenericGenerator, which is perfect solution for my question. Essentially making it available for all entities.

code of the generator;

public class MyGenerator implements IdentifierGenerator {

    public static final String generatorName = "myGenerator";

    @Override
    public Serializable generate(SharedSessionContractImplementor sharedSessionContractImplementor, Object object) throws HibernateException {
        return GeneratorUtil.generate();
    }
}

and the entities in the following state;

@Entity
@Table(name = "CHAIRS")
public class ChairEntity {

    @Id
    @GeneratedValue(generator = MyGenerator.generatorName)
    protected String id;

    // rest of the entity
}

Which did the trick, now the @GenericGenerator is defined in a single location, supplying the MyGenerator details to all my entities, if any of them wishes to use it, they just utilize @GeneratedValue.

1
On

You could also use @MappedSuperclass

@MappedSuperclass
public abstract class BaseEntity {

    @Id
    @GeneratedValue(generator = "myGenerator")
    @GenericGenerator(strategy = "a.b.jpa.generator.MyGenerator", name = "myGenerator")
    protected String id;

    // getters, setters here

}

Then, your Entities can extend it:

@Entity
@Table(name = "CHAIRS")
public class ChairEntity extends BaseEntity { ... }