1

I use EclipseLink and I get very strange results. Please, consider the following code:

This code works:

@Entity
@Table(name = "someTable")
public class SomeClass{
    @Id// PAY ATTENTION TO THIS LINE
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Column (name = "somecol")// PAY ATTENTION TO THIS LINE
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

This code also works:

@Entity
@Table(name = "someTable")
public class SomeClass{
    @Id// PAY ATTENTION TO THIS LINE
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    //@Column (name = "somecol")// PAY ATTENTION TO THIS LINE
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

This code also works:

@Entity
@Table(name = "someTable")
public class SomeClass{

    private String id;

    @Id// PAY ATTENTION TO THIS LINE
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    //@Column (name = "somecol")// PAY ATTENTION TO THIS LINE
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

This code DOESN'T work:

@Entity
@Table(name = "someTable")
public class SomeClass{

    private String id;

    @Id // PAY ATTENTION TO THIS LINE
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Column (name = "somecol")// PAY ATTENTION TO THIS LINE
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

I get the following exception:

Exception Description: Entity class [class SomeClass] has no primary key specified. It should define either an @Id, @EmbeddedId or an @IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
    at org.eclipse.persistence.exceptions.ValidationException.noPrimaryKeyAnnotationsFound(ValidationException.java:1425)
    at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.validatePrimaryKey(EntityAccessor.java:1542)
    at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.processMappingAccessors(EntityAccessor.java:1249)
    at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.process(EntityAccessor.java:699)
    at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processStage2(MetadataProject.java:1808)
    at org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor.processORMMetadata(MetadataProcessor.java:573)
    at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processORMetadata(PersistenceUnitProcessor.java:607)
    at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1948)
    at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.callPredeploy(JPAInitializer.java:100)
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactoryImpl(PersistenceProvider.java:104)
    at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:188)
    at org.eclipse.gemini.jpa.ProviderWrapper.createEntityManagerFactory(ProviderWrapper.java:128)
    at org.eclipse.gemini.jpa.proxy.EMFServiceProxyHandler.createEMF(EMFServiceProxyHandler.java:151)
    at org.eclipse.gemini.jpa.proxy.EMFServiceProxyHandler.syncGetEMFAndSetIfAbsent(EMFServiceProxyHandler.java:127)
    at org.eclipse.gemini.jpa.proxy.EMFServiceProxyHandler.invoke(EMFServiceProxyHandler.java:73)
    at com.sun.proxy.$Proxy8.createEntityManager(Unknown Source)

Why doesn't last code work? How to explain it?

Pavel_K
  • 10,748
  • 13
  • 73
  • 186

1 Answers1

4

That's because there is something like @Access which you must specify on a entity and field level if you would like to use the mixed mode. There are two values AccessType.PROPERTY and AccesType.FIELD.

The default access type is defined by where you put your identifier annotation (@Id). If you put it on the field - it will be AccessType.FIELD, if you put it on the getter - it will be AccessType.PROPERTY. - edited, not defined by JPA.

If you want to annotate not fields but properties (still having @Id on field) you must define a getter and annotate it as AccessType.PROPERTY. (or vice versa for @Id on getter).

gmaslowski
  • 774
  • 5
  • 13
  • I am confused: If the place `@Id` is placed decide the `AccessType`, why would it complain for "has no primary key specified"? Base on your answer, the last example will default to `AccessType.PROPERTY` and the `@Id` annotation is putting at the correct place isn't it? – Adrian Shum May 17 '16 at 06:19
  • just a further search give me this answer: http://stackoverflow.com/a/13874900/395202 What you said is the same as the **answer** but it turned out, in the **comment** section of the answer, suggested such behavior (`@Id` decides `AccessType`) is not JPA standard. (And it doesn't explain the behavior OP is facing too) – Adrian Shum May 17 '16 at 06:27
  • I've just read what you posted. Honestly I remember that about AccessType - simply because I have a exercise about it on my JPA training (but I use Hibernate as the provider). What I understood right now is that EclipseLink treats it differently. Nevertheless, you're right. My answer didn't answer the actual question, which was why there's no-PK-exception :). But for sure helped to avoid the symptoms. – gmaslowski May 17 '16 at 07:00
  • I guess JPA's standard insist the access type need to be standard through out the class (even in the whole hierarchy I believe). It is vendor's choice to decide how to deal with cases of inconsistency. Good answer though as it give the correct direction for other (incl me) to find out more for the problem :) – Adrian Shum May 17 '16 at 07:55