JPA:在fied和getter上设置@Id之间的区别

时间:2016-05-17 05:36:53

标签: java jpa eclipselink

我使用EclipseLink,结果非常奇怪。请考虑以下代码:

此代码有效:

@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;
    }
}

此代码也有效:

@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;
    }
}

此代码也有效:

@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;
    }
}

此代码不起作用:

@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;
    }
}

我得到以下异常:

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)

为什么上次代码不起作用?怎么解释呢?

1 个答案:

答案 0 :(得分:3)

那是因为如果您想使用混合模式,您必须在实体和字段级别指定@Access之类的内容。有两个值AccessType.PROPERTYAccesType.FIELD

默认访问类型由您放置标识符注释(@Id)的位置定义。如果你将它放在字段上 - 它将是AccessType.FIELD,如果你把它放在getter上 - 它将是AccessType.PROPERTY - 编辑,不是由JPA定义的。

如果要注释不是字段而是属性(在字段上仍然有@Id),则必须定义一个getter并将其注释为AccessType.PROPERTY。 (对于getter上的@Id反之亦然。)