简体   繁体   中英

JPA: Using @Embeddable and @EmbeddedId with interfaces

I want to implement the following two interfaces and map them to a database using JPA and Hibernate.

public interface IThing {
    public IKey getId();
    public void setId(IKey id);
}

public interface IKey {
    public String getS();
    public void setS(String s);
    public Boolean getB();
    public void setB(Boolean b);
}

So a Key should be an object with two fields. Their names and types don't matter. The important thing is that Key is a compound key for Thing .

Simple (or whatever is considered simple for Java code) implementations:

@Entity
public class Thing implements IThing, java.io.Serializable {
    @EmbeddedId
    private IKey id;

    public IKey getId() {
       return this.id;
    }
    public void setId(IKey id) {
        this.id = id;
    }
}

@Embeddable
public class Key implements IKey, java.io.Serializable {
    private String s;
    private Boolean b;

    public String getS() {
        return s;
    }
    public void setS(String s) {
        this.s = s;
    }

    public Boolean getB() {
        return b;
    }
    public void setB(Boolean b) {
        this.b = b;
    }
}

Now, you don't even have to use them, their mere presence and the creation of an EntityManager seem to be enough to trigger this:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: example] Unable to configure EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:378)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:56)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
    at example.Main.main(Main.java:7)
    ... 6 more
Caused by: org.hibernate.AnnotationException: example.IKey has no persistent id property: example.Thing.id
    at org.hibernate.cfg.AnnotationBinder.bindComponent(AnnotationBinder.java:2301)
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2021)
    at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:796)
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:707)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:4035)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3989)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1398)
    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1375)
    at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1519)
    at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1100)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:282)
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:366)
    ... 10 more

While I can use this (note how it is not implementing IThing and ignoring the IKey interface) without error:

@Entity
public class Thing2 implements java.io.Serializable {
    @EmbeddedId
    private Key id;

    public Key getId() {
       return this.id;
    }
    public void setId(Key id) {
        this.id = id;
    }
}

I did not find any way to make the version using interfaces work. Is it possible to implement the two interfaces and make the resulting implementation classes into proper JPA @Entity and @EmbeddedId ?

(This might be related to this other question , at least the error is similar.)

I'm not sure if it is possible.

Use interface for this purpose in my experience with reflection is impossible because first of all the @Embeddable is applied on target class and not on the interface an then in many case the mechanism of many framework with reflection need of a specific class for be able to instance the class.... for an interface of course will be impossible instance it because interface in Java is a special case of abstract class.

I hope that this can help you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM