I have to deal with a view declared as following (Oracle 11g):
create view V_SOME_VIEW as
select X, Y
from SOME_TABLE
and an entity for it:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
@Entity
@Table("V_SOME_VIEW")
@NamedQueries({
@NamedQuery(name = "VSomeView.findAll", query = "SELECT v FROM VSomeView v")})
public class VSomeView implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Lob
@Column(name = "X")
private Object x;
@Lob
@Column(name = "Y")
private Object y;
...
}
After generating a static metamodel using Gradle Metamodel Plugin I have the following metamodel without attribute y:
import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(VSomeView.class)
public abstract class VSomeView_ {
public static volatile SingularAttribute<VSomeView, Object> x;
public static final String X = "x";
}
At application start I have errors like this:
ERROR o.h.ejb.metamodel.MetadataContext: HHH015011: Unable to locate static metamodel field: ...VSomeView_#y
If I change column type from java.lang.Object
to java.lang.String
the field y is generated correctly. Can someone explain me, what's the reason for this, please?
From JPA specification
6.2.1.1 Canonical Metamodel
For every persistent non-collection-valued attribute
y
declared by classX
, where the type ofy
isY
, the metamodel class must contain a declaration as follows:
public static volatile SingularAttribute<X, Y> y;
So, from this point of view, your expectation to see y
property in the metamodel class looks substantiated.
But diving into the Hibernate implementation of the annotation processor JPAMetaModelEntityProcessor, we can find out that a non-collection-valued attribute will be present at the metamodel class if the method isBasicAttribute of the class MetaAttributeGenerationVisitor returns true.
It is possible in the following cases:
The persistent attribute is annotated by one of the following annotations: @Basic, @OneToOne, @ManyToOne, @EmbeddedId, @Id.
The persistent attribute is annotated with the annotation @Type what means it is a hibernate custom type.
The persistent attribute is an enum.
The persistent attribute is a primitive type
The persistent attribute is a hibernate basic type
The persistent attribute is a class that implements Serializable interface.
The persistent attribute is a class annotated with the @Embeddable annotation.
Your first persistent attribute meet the n.1 condition due to the @Id
annotation, but the second one does not meet n.1-7 conditions that is why it is absent in the generated metamodel.
See also this.