JPA:在 fied 和 getter 上设置 @Id 的区别
JPA: difference between setting @Id on fied and on getter
我使用 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)
为什么最后的代码不起作用?怎么解释?
那是因为有类似 @Access
的内容,如果您想使用混合模式,则必须在实体和字段级别指定。有两个值 AccessType.PROPERTY
和 AccesType.FIELD
.
默认访问类型由您放置标识符注释的位置定义 (@Id
)。如果你把它放在字段上 - 它将是 AccessType.FIELD
,如果你把它放在 getter - 它将是 AccessType.PROPERTY
。 - 编辑,不是由 JPA 定义.
如果你想注释的不是字段而是属性(字段上仍然有@Id)你必须定义一个getter并将它注释为AccessType.PROPERTY
。 (或者 getter 上的 @Id
反之亦然)。
我使用 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)
为什么最后的代码不起作用?怎么解释?
那是因为有类似 @Access
的内容,如果您想使用混合模式,则必须在实体和字段级别指定。有两个值 AccessType.PROPERTY
和 AccesType.FIELD
.
默认访问类型由您放置标识符注释的位置定义 ( - 编辑,不是由 JPA 定义.@Id
)。如果你把它放在字段上 - 它将是 AccessType.FIELD
,如果你把它放在 getter - 它将是 AccessType.PROPERTY
。
如果你想注释的不是字段而是属性(字段上仍然有@Id)你必须定义一个getter并将它注释为AccessType.PROPERTY
。 (或者 getter 上的 @Id
反之亦然)。