Search code examples
jpahibernate-5.xmetamodel

JPA Hibernate 5: OneToOne in nested Embeddable causes metamodel issue


I have an entity:

@Entity
public class Test {

    @Embedded
    Content content;

// getters setters..
}

This contains an embedded class as you can see:

@Embeddable
public class Content {

    @OneToOne
    Person person;

    @Embedded
    Language language;

// getters setters..
}

This contains again an embeddable. 2 times nested embeddable

@Embeddable
public class Language {

    String format;

    @OneToOne
    IdentifierCode identifierCode;

// getters setters..
}

When using the automatic schema generation feature of JPA all columns are generated in the correct way.

I use the @Data annotation on each @Entity and @Embeddable to generate getters, setters, constructors, etc..

When starting the application server (EAP 7), I notice this warning in the logs:

HHH015011: Unable to locate static metamodel field : org.package.Language_#identifierCode; this may or may not indicate a problem with the static metamodel

Indeed, when opening the metamodel class Language_; no identifierCode column reference is present:

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Language.class)
public abstract class Language_ {

    public static volatile SingularAttribute<Language, String> format;

}

I don't see what I'm doing wroing. Is it not possible to use @OneToOne in a nested @Embeddable? The metamodel Content_ correctly generates the singular attribute for person!

It seems when using multiple nested embeddables, something goes wrong. When using only one level of embeddables, it works.

I tried other stuff:

  1. Adding Access.Field on the class. Nothing happens.
  2. Instantiation the @Embedded class, like @Embedded Language language = new Language(). Nothing happens.
  3. Replaced the @OneToOne with @ManyToOne. Nothing happens.

Solution

  • This sounds like a bug in your JPA provider, which you should report to them.

    The JPA provider I use (DataNucleus) creates a public static volatile SingularAttribute<Language, mydomain.model.IdentifierCode> identifierCode;

    One option you have is to just use the datanucleus-jpa-query.jar in your CLASSPATH to generate the static metamodel and use those generated classes with your existing provider, alternatively use it for persistence too.