Issue
I have a custom ID generator that generates an UUID string with a prefix for my entities ID, but since I'm using different prefix for each entity I'm having to create one ID generation class for each Entity, is there a way to only use one class for this?
My ID generation class is this:
import java.io.Serializable;
import java.util.UUID;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator;
public class ProductIdGenerator implements IdentifierGenerator{
public static final String generatorName = "produtcIdGenerator";
@Override
public Serializable generate(SharedSessionContractImplementor arg0, Object arg1) throws
HibernateException {
String prefix = "PROD";
String uuid = UUID.randomUUID().toString().substring(0, 8);
return prefix + uuid;
}
}
My Entities looks like this:
@Entity
public class Product {
@Id
@GeneratedValue(generator = ProductIdGenerator.generatorName)
@GenericGenerator(name = ProductIdGenerator.generatorName, strategy = "net.ddns.mrq.util.ProductIdGenerator")
@Column(name = "product_id")
private String id;
private String name;
.
.
.
I have 8 entities and I had to create 8 classes like this for each of one them with different prefix.
- Is there a way to make this more dynamic and less "time consuming"?
- Is there a way to only change the prefix for each class without creating multiple id generation classes?
Solution
I can think of a couple of ways to solve this (which is basically the need for a custom IdentifierGenerator
to be parameterized).
One idea involves each entity implementing an interface that can return the appropriate ID prefix for that entity type. Since the target entity is passed to the generator's generate()
method, the generator could cast it to that interface and ask it for the prefix to use.
Another solution takes advantage of the fact that IdentifierGenerator
s can implement the org.hibernate.id.Configurable
interface to have configuration "injected" into them, and the @GenericGenerator
annotation supports setting those as @Parameter
s in the annotation. That way, each usage of @GenericGenerator
can dictate what prefix it wants the custom generator to use. It would look something like this (note, this is untested code):
public class ProductIdGenerator implements IdentifierGenerator, org.hibernate.id.Configurable {
public static final String GENERATOR_NAME = "produtcIdGenerator";
public static final String PREFIX_PARAM = "prefix";
private String prefix = "";
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
this.prefix = params.getProperty(PREFIX_PARAM, "");
}
@Override
public Serializable generate(SharedSessionContractImplementor session, Object entityObject) throws HibernateException {
String uuid = UUID.randomUUID().toString().substring(0, 8);
return prefix + uuid;
}
}
References to it would look like this:
@Id
@GeneratedValue(generator = ProductIdGenerator.GENERATOR_NAME)
@GenericGenerator(
name = ProductIdGenerator.GENERATOR_NAME,
strategy = "net.ddns.mrq.util.ProductIdGenerator",
parameters = {@Parameter(name = ProductIdGenerator.PREFIX_PARAM, value = "foo")})
private String id;
Personally, I find the second idea a little cleaner, but there's nothing wrong with the first that I can see. It's a matter of style.
Answered By - E-Riz
Answer Checked By - Candace Johnson (JavaFixing Volunteer)