JPA OneToMany映射异常:字段XXX无法声明它被另一个字段映射
JPA OneToMany mapping exception: Field XXX cannot declare that it is mapped by another field
在我的项目中,我有下面报告的 类,具有双向关系映射。当我尝试通过 JPA 读取 DataProviderImpl 类型的对象时,出现以下异常:
org.apache.openjpa.persistence.ArgumentException: Field "persistence.entity.DataProviderImpl.methods" cannot declare that it is mapped by another field. Its mapping strategy( org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy) does not support mapping by another field.
我已经检查了其他问题,但似乎没有任何问题适用于我的情况。有什么提示吗?
提前致谢!
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="DataProvider" transaction-type="JTA"> <!-- transaction-type="RESOURCE_LOCAL" info at: http://tomee.apache.org/jpa-concepts.html -->
<jta-data-source>
osgi:service/jdbc/mysqlPoolXAds
</jta-data-source>
<non-jta-data-source>
osgi:service/jdbc/mysqlds
</non-jta-data-source>
<class>persistence.entity.DataProviderImpl</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
<persistence-unit name="RestMethod" transaction-type="JTA"> <!-- transaction-type="RESOURCE_LOCAL" info at: http://tomee.apache.org/jpa-concepts.html -->
<jta-data-source>
osgi:service/jdbc/mysqlPoolXAds
</jta-data-source>
<non-jta-data-source>
osgi:service/jdbc/mysqlds
</non-jta-data-source>
<class>persistence.entity.RestMethodImpl</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
@Entity(name = "DataProvider")
public class DataProviderImpl implements DataProvider {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
// ...
@OneToMany(fetch = FetchType.LAZY, mappedBy="dataProvider")
private List<RestMethod> methods;
public DataProviderImpl() {
super();
this.id = 0;
}
@Override
public int getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public List<RestMethod> getMethods() {
return methods;
}
@Override
public void setMethods(List<RestMethod> methods) {
this.methods = methods;
}
}
public interface DataProvider {
public int getId();
public void setId(int id);
public String getName();
public void setName(String name);
public List<RestMethod> getMethods();
public void setMethods(List<RestMethod> methods);
}
@Entity(name = "RestMethod")
public class RestMethodImpl implements RestMethod {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String nickname;
// ...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="dataProviderId")
private DataProvider dataProvider;
public RestMethodImpl() {
super();
this.id = 0;
}
@Override
public int getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
@Override
public String getNickname() {
return nickname;
}
@Override
public void setNickname(String nickname) {
this.nickname = nickname;
}
@Override
public DataProvider getDataProvider() {
return dataProvider;
}
@Override
public void setDataProvider(DataProvider dataProvider) {
this.dataProvider = dataProvider;
}
}
public interface RestMethod {
public int getId();
public void setId(int id);
public String getNickname();
public void setNickname(String nickname);
public DataProvider getDataProvider();
public void setDataProvider(DataProvider dataProvider);
}
假设您使用了来自 javax.persistence
的导入语句,您的映射注释绝对应该使用额外的参数 targetEntity=...
,否则对象关系映射器无法准确确定哪个 class 是为给定的接口类型实例化,例如 RestMethod
。所以你的映射将是:
@Entity(name = "DataProvider")
public class DataProviderImpl implements DataProvider {
// ...
@OneToMany(targetEntity=RestMethodImpl.class, fetch = FetchType.LAZY, mappedBy="dataProvider")
private List<RestMethod> methods;
因此:
@Entity(name = "RestMethod")
public class RestMethodImpl implements RestMethod {
// ...
@ManyToOne(targetEntity=DataProviderImpl.class, fetch = FetchType.LAZY)
@JoinColumn(name="dataProviderId")
private DataProvider dataProvider;
我不知道这对你的情况是否有帮助,但你当然应该尝试使用 JPA 映射器的这些额外信息来调整你的代码。
我刚发现您给定的 persistence.xml
的另一个问题。您应该在同一个 persistence-unit
块中同时拥有 classes(DataProviderImpl
和 RestMethodImpl
),因为根据您的配置构建的实体上下文必须了解这两个 class es 施加正确的映射策略。
在我的项目中,我有下面报告的 类,具有双向关系映射。当我尝试通过 JPA 读取 DataProviderImpl 类型的对象时,出现以下异常:
org.apache.openjpa.persistence.ArgumentException: Field "persistence.entity.DataProviderImpl.methods" cannot declare that it is mapped by another field. Its mapping strategy( org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy) does not support mapping by another field.
我已经检查了其他问题,但似乎没有任何问题适用于我的情况。有什么提示吗? 提前致谢!
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="DataProvider" transaction-type="JTA"> <!-- transaction-type="RESOURCE_LOCAL" info at: http://tomee.apache.org/jpa-concepts.html -->
<jta-data-source>
osgi:service/jdbc/mysqlPoolXAds
</jta-data-source>
<non-jta-data-source>
osgi:service/jdbc/mysqlds
</non-jta-data-source>
<class>persistence.entity.DataProviderImpl</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
<persistence-unit name="RestMethod" transaction-type="JTA"> <!-- transaction-type="RESOURCE_LOCAL" info at: http://tomee.apache.org/jpa-concepts.html -->
<jta-data-source>
osgi:service/jdbc/mysqlPoolXAds
</jta-data-source>
<non-jta-data-source>
osgi:service/jdbc/mysqlds
</non-jta-data-source>
<class>persistence.entity.RestMethodImpl</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
@Entity(name = "DataProvider")
public class DataProviderImpl implements DataProvider {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
// ...
@OneToMany(fetch = FetchType.LAZY, mappedBy="dataProvider")
private List<RestMethod> methods;
public DataProviderImpl() {
super();
this.id = 0;
}
@Override
public int getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public List<RestMethod> getMethods() {
return methods;
}
@Override
public void setMethods(List<RestMethod> methods) {
this.methods = methods;
}
}
public interface DataProvider {
public int getId();
public void setId(int id);
public String getName();
public void setName(String name);
public List<RestMethod> getMethods();
public void setMethods(List<RestMethod> methods);
}
@Entity(name = "RestMethod")
public class RestMethodImpl implements RestMethod {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String nickname;
// ...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="dataProviderId")
private DataProvider dataProvider;
public RestMethodImpl() {
super();
this.id = 0;
}
@Override
public int getId() {
return id;
}
@Override
public void setId(int id) {
this.id = id;
}
@Override
public String getNickname() {
return nickname;
}
@Override
public void setNickname(String nickname) {
this.nickname = nickname;
}
@Override
public DataProvider getDataProvider() {
return dataProvider;
}
@Override
public void setDataProvider(DataProvider dataProvider) {
this.dataProvider = dataProvider;
}
}
public interface RestMethod {
public int getId();
public void setId(int id);
public String getNickname();
public void setNickname(String nickname);
public DataProvider getDataProvider();
public void setDataProvider(DataProvider dataProvider);
}
假设您使用了来自 javax.persistence
的导入语句,您的映射注释绝对应该使用额外的参数 targetEntity=...
,否则对象关系映射器无法准确确定哪个 class 是为给定的接口类型实例化,例如 RestMethod
。所以你的映射将是:
@Entity(name = "DataProvider")
public class DataProviderImpl implements DataProvider {
// ...
@OneToMany(targetEntity=RestMethodImpl.class, fetch = FetchType.LAZY, mappedBy="dataProvider")
private List<RestMethod> methods;
因此:
@Entity(name = "RestMethod")
public class RestMethodImpl implements RestMethod {
// ...
@ManyToOne(targetEntity=DataProviderImpl.class, fetch = FetchType.LAZY)
@JoinColumn(name="dataProviderId")
private DataProvider dataProvider;
我不知道这对你的情况是否有帮助,但你当然应该尝试使用 JPA 映射器的这些额外信息来调整你的代码。
我刚发现您给定的 persistence.xml
的另一个问题。您应该在同一个 persistence-unit
块中同时拥有 classes(DataProviderImpl
和 RestMethodImpl
),因为根据您的配置构建的实体上下文必须了解这两个 class es 施加正确的映射策略。