Budzu Budzu - 4 months ago 24
Java Question

Hibernate unbound type and no explicit target entity when using generic

I have the following two classes:

@Entity
@Table(name = "criteria")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = AbstractCriteria.TYPE, discriminatorType = DiscriminatorType.STRING)
public abstract class AbstractCriteria<T> implements Serializable {

public static final String TYPE = "type";

...
@Column(name = "clazz") private Class<T> clazz;
...

protected AbstractCriteria(Class<T> clazz) {
this.clazz = Preconditions.checkNotNull(clazz);
}
...

public abstract Predicate<T> evaluate(T value);
}

@Entity
@DiscriminatorValue(CriteriaType.Values.DATETIME_IS_BETWEEN)
public class DateTimeIsBetweenCriteria extends AbstractCriteria<DateTime> {
...
public DateTimeIsBetweenCriteria() {
super(DateTime.class);
}
...


@Override
public Predicate<DateTime> evaluate(DateTime value) {
...
}
}


When I tried to save an instance of the DateTimeIsBetweenCriteria class, I got this exception:

Exception in thread "main" org.hibernate.AnnotationException:
Property ...AbstractCriteria.clazz has an unbound type and no explicit target entity.
Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type


I need
clazz
for a method in
AbstractCriteria
, and
T
can be String, DateTime, Boolean, etc.

I was thinking about making
clazz
@Transient
, but if I do that, I still have to have another column to identify which criteria to save so that when loading the criteria back from the database, I know which kind of criteria it is. I think this is kinda hacky.

Any ideas how I can resolve that exception without changing my design?

I appreciate your time a lot.

Answer Source

I have changed my implementation to not using parameterized type:

@Entity 
@Table(name = "criteria") 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = AbstractCriteria.TYPE, discriminatorType = DiscriminatorType.STRING)
public abstract class AbstractCriteria implements Serializable {

  public static final String TYPE = "type";

  ...
  @Column(name = "clazz") private Class clazz;
  ...

  protected AbstractCriteria(Class clazz) {
     this.clazz = Preconditions.checkNotNull(clazz);
  }
  ...

  public abstract Predicate evaluate(Object value);
}

@Entity 
@DiscriminatorValue(CriteriaType.Values.DATETIME_IS_BETWEEN) 
public class DateTimeIsBetweenCriteria extends AbstractCriteria {
  ...
  public DateTimeIsBetweenCriteria() {
     super(DateTime.class);
  }
  ...


  @Override 
  public Predicate evaluate(Object value) {
     if (value instanceof DateTime) {
        // do evaluation and return here.
     } else {
        throw new UserDefinedException("...");
     }
  }
}