JPA OneToMany映射异常:字段XXX无法声明它由另一个字段映射

时间:2015-01-16 13:24:52

标签: java jpa

在我的项目中,我有下面报告的类,具有双向关系映射。当我尝试通过JPA读取DataProviderImpl类型的对象时,我得到以下异常:

  

org.apache.openjpa.persistence.ArgumentException:Field" persistence.entity.DataProviderImpl.methods"不能声明它是由另一个字段映射的。它的映射策略(org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy)不支持另一个字段的映射。

我已经检查了其他问题,但在我的案例中似乎没有任何内容。任何提示? 提前谢谢!

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

1 个答案:

答案 0 :(得分:6)

假设您使用了来自javax.persistence的import语句,您的映射注释肯定应该使用额外的参数targetEntity=...,否则对象关系映射器无法准确地确定要为给定的接口类型实例化哪个类,例如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的另一个问题。您应该在同一个DataProviderImpl块中同时拥有这两个类(RestMethodImplpersistence-unit),因为从您的配置构建的实体上下文必须知道这两个类才能产生正确的映射策略。