JPA Map与EveryClass的ManyToOne关系 - persistence.ArgumentException

时间:2012-03-08 12:44:32

标签: java exception jpa

我想用Apache OpenJPA 2.2.0映射两个具有manyToOne / oneToMay关系的类。 一个classe有两个属性的主键:

@Entity(name = "Player")
@IdClass(PlayerId.class)
public class Player {
    @Id
    private String nickname;
    @Id
    @ManyToOne(cascade = CascadeType.PERSIST)
    @JoinColumn(name = "team_id")
    private Team team;

    public Player() {

    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public Team getTeam() {
        return team;
    }

    public void setTeam(Team team) {
        this.team = team;
    }

}

public class PlayerId {
    private String nickname;
    private Team team;

    public PlayerId() {
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public Team getTeam() {
        return team;
    }

    public void setTeam(Team team) {
        this.team = team;
    }

    @Override
    public boolean equals(Object o) {
        return ((o instanceof PlayerId) && 
                this.nickname == ((PlayerId)o).getNickname() &&
                this.team == ((PlayerId) o).getTeam());
    }

    public int hashCode() {
        return nickname.hashCode() + team.hashCode();
    }
}

@Entity(name = "Team")
public class Team {
    @Id
    private String name;

    @OneToMany(mappedBy = "team", targetEntity = Player.class, fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    private List<Player> players;

    public Team() {

    }

    public List<Player> getPlayers() {
        return players;
    }

    public void setPlayers(List<Player> p) {
        players = p;
    }

    public String getName() {
        return name;
    }

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

所以当我与一个团队一起创建一个新玩家时,我会得到以下几个例外:

Exception in thread "main" <openjpa-2.2.0-r422266:1244990 fatal user error> org.apache.openjpa.persistence.ArgumentException: Errors encountered while resolving metadata.  See nested exceptions for details.
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:668)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:411)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:384)
    at org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:714)
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:643)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:411)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:384)
    at org.apache.openjpa.jdbc.meta.MappingRepository.getMapping(MappingRepository.java:355)
    at org.apache.openjpa.jdbc.meta.MappingTool.getMapping(MappingTool.java:682)
    at org.apache.openjpa.jdbc.meta.MappingTool.buildSchema(MappingTool.java:754)
    at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:652)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:154)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:164)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newBrokerImpl(JDBCBrokerFactory.java:122)
    at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:209)
    at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:154)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:60)
    at main.Main.main(Main.java:27)
Caused by: <openjpa-2.2.0-r422266:1244990 fatal user error> org.apache.openjpa.persistence.ArgumentException: The id class specified by type "class model.Player" does not match the primary key fields of the class.  Make sure your identity class has the same primary keys as your persistent type, including pk field types. Mismatched property: "team"
    at org.apache.openjpa.meta.ClassMetaData.validateAppIdClassPKs(ClassMetaData.java:2216)
    at org.apache.openjpa.meta.ClassMetaData.validateAppIdClass(ClassMetaData.java:2090)
    at org.apache.openjpa.meta.ClassMetaData.validateIdentity(ClassMetaData.java:2026)
    at org.apache.openjpa.meta.ClassMetaData.validateMeta(ClassMetaData.java:1938)
    at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1799)
    at org.apache.openjpa.meta.MetaDataRepository.processBuffer(MetaDataRepository.java:822)
    at org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:719)
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:643)
    ... 19 more
NestedThrowables:
<openjpa-2.2.0-r422266:1244990 fatal user error> org.apache.openjpa.persistence.ArgumentException: Attempt to map "model.Player.team" failed: the owning entity is not mapped.
    at org.apache.openjpa.jdbc.meta.MappingInfo.assertTable(MappingInfo.java:628)
    at org.apache.openjpa.jdbc.meta.MappingInfo.createForeignKey(MappingInfo.java:1079)
    at org.apache.openjpa.jdbc.meta.ValueMappingInfo.getTypeJoin(ValueMappingInfo.java:115)
    at org.apache.openjpa.jdbc.meta.ValueMappingInfo.getTypeJoin(ValueMappingInfo.java:92)
    at org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy.map(RelationFieldStrategy.java:167)
    at org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:146)
    at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:82)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:496)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:461)
    at org.apache.openjpa.jdbc.meta.strats.RelationToManyInverseKeyFieldStrategy.map(RelationToManyInverseKeyFieldStrategy.java:135)
    at org.apache.openjpa.jdbc.meta.strats.RelationCollectionInverseKeyFieldStrategy.map(RelationCollectionInverseKeyFieldStrategy.java:95)
    at org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:146)
    at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:82)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:496)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:461)
    at org.apache.openjpa.jdbc.meta.ClassMapping.resolveMapping(ClassMapping.java:854)
    at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1802)
    at org.apache.openjpa.meta.MetaDataRepository.processBuffer(MetaDataRepository.java:822)
    at org.apache.openjpa.meta.MetaDataRepository.resolveMapping(MetaDataRepository.java:777)
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:657)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:411)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:384)
    at org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:714)
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:643)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:411)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:384)
    at org.apache.openjpa.jdbc.meta.MappingRepository.getMapping(MappingRepository.java:355)
    at org.apache.openjpa.jdbc.meta.MappingTool.getMapping(MappingTool.java:682)
    at org.apache.openjpa.jdbc.meta.MappingTool.buildSchema(MappingTool.java:754)
    at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:652)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:154)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:164)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newBrokerImpl(JDBCBrokerFactory.java:122)
    at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:209)
    at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:156)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:227)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:154)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:60)
    at main.Main.main(Main.java:27)

我知道为什么我会这样,但我无法解决它。 有人能帮助我吗?

当我使用没有IdClass的生成主键(可能是长ID)时没有问题。 但我需要IdClass。

最诚挚的问候 Veote

2 个答案:

答案 0 :(得分:1)

我的猜测:

public class PlayerId {
    private String nickname;
    private Team team;  -> this should be "name" to match the Id in the class Team.

...

}

我认为在这种情况下使用@EmbeddedId更容易。见http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/

网站上的简单示例:

@Entity
class User {
  @EmbeddedId
  @AttributeOverride(name="firstName", column=@Column(name="fld_firstname")
  UserId id;

  Integer age;
}

@Embeddable
class UserId implements Serializable {
  String firstName;
  String lastName;
}

我也会从PlayerId类中移除Team,这看起来似乎不是一个合乎逻辑的设计选择。

答案 1 :(得分:0)

我遇到了同样的问题,并在此处找到了我的解决方案: https://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/DerivedIdentifiers

您不应在idClass中添加实体,而应添加实体的ID。所以试试

public class PlayerId {
   private String nickname;
   private String team;

   ...
}