You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Christian Defoy <ch...@gmail.com> on 2007/09/06 17:45:39 UTC
Join table with extra value
Hello,
I have two objects, A and B, that are involved in a many to many
relationship. That portion works ok if class A contains:
@ManyToMany( fetch=FetchType.EAGER, cascade=CascadeType.ALL )
@JoinTable( name="a_b", joinColumns=@JoinColumn( name="a_id",
referencedColumnName="a_id" ),
inverseJoinColumns=@JoinColumn( name="b_id",
referencedColumnName="b_id" ))
private Set<B> mappedBs;
My problem is that the relationship between A and B must contain an
additional value. The join table between A and B looks like this:
create table A_B
(
a_id integer not null,
b_id integer not null,
value integer
);
Should I define the mapping as A (OneToMany) A_B (ManyToOne) B and
create an object for A_B? If so, how do I do that?
Thanks in advance!
Christian
Re: Join table with extra value
Posted by Christian Defoy <ch...@gmail.com>.
Patrick,
> What goes into the value column?
The value column contains the size of the portion of A provided by B.
In other words, it is not a key of some sort but rather data that is
relevant to the association between A and B.
> You certainly could take that approach. You'd just set up a pair of
> one-to-many relations from A to A_B and B to A_B; you wouldn't need to
> do anything special to make it work.
To my understanding, every entity has to provide an ID for itself but
A_B does not have any column for that. Instead, the primary key of
the table is (a_id, b_id). This means that the key for A_B is really
the key of A and the key of B. I can use the technique described in
section 5.3.2 "Entities as Identity Fields" to do that. It works fine
in my test app. As long as B is already in the database, I can get A
and A_B to persist correctly.
When I do the same in my real app, I get the following exceptions:
Exception in thread "main" <0.9.7-incubating 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:506)
at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:288)
at org.apache.openjpa.kernel.TestWithListBrokerImpl.persist(TestWithListBrokerImpl.java:2352)
at org.apache.openjpa.kernel.TestWithListBrokerImpl.persist(TestWithListBrokerImpl.java:2204)
at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1010)
at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:541)
at ex9.Helper.testMappingSave(Helper.java:414)
at ex9.Helper.run(Helper.java:81)
at ex9.Helper.main(Helper.java:736)
Caused by: java.lang.NullPointerException
at org.apache.openjpa.jdbc.meta.MappingInfo.mergeJoinColumn(MappingInfo.java:1386)
at org.apache.openjpa.jdbc.meta.MappingInfo.createJoins(MappingInfo.java:1192)
at org.apache.openjpa.jdbc.meta.MappingInfo.createForeignKey(MappingInfo.java:954)
at org.apache.openjpa.jdbc.meta.ValueMappingInfo.getTypeJoin(ValueMappingInfo.java:104)
at org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy.map(RelationFieldStrategy.java:147)
at org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:120)
at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:80)
at org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:438)
at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:403)
at org.apache.openjpa.jdbc.meta.ClassMapping.resolveNonRelationMappings(ClassMapping.java:813)
at org.apache.openjpa.jdbc.meta.MappingRepository.prepareMapping(MappingRepository.java:319)
at org.apache.openjpa.meta.MetaDataRepository.preMapping(MetaDataRepository.java:605)
at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:492)
... 8 more
NestedThrowables:
java.lang.NullPointerException
at org.apache.openjpa.jdbc.meta.FieldMapping.initializeMapping(FieldMapping.java:486)
at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:405)
at org.apache.openjpa.jdbc.meta.ClassMapping.initializeMapping(ClassMapping.java:834)
at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1590)
at org.apache.openjpa.meta.MetaDataRepository.resolveMapping(MetaDataRepository.java:629)
at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:498)
at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:288)
at org.apache.openjpa.kernel.TestWithListBrokerImpl.persist(TestWithListBrokerImpl.java:2352)
at org.apache.openjpa.kernel.TestWithListBrokerImpl.persist(TestWithListBrokerImpl.java:2204)
at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1010)
at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:541)
at ex9.Helper.testMappingSave(Helper.java:414)
at ex9.Helper.run(Helper.java:81)
at ex9.Helper.main(Helper.java:736)
<0.9.7-incubating fatal user error>
org.apache.openjpa.persistence.ArgumentException: Field "..." declares
"..." as its mapped-by field, but this field is not a direct relation.
at org.apache.openjpa.jdbc.meta.strats.RelationToManyInverseKeyFieldStrategy.map(RelationToManyInverseKeyFieldStrategy.java:126)
at org.apache.openjpa.jdbc.meta.strats.RelationCollectionInverseKeyFieldStrategy.map(RelationCollectionInverseKeyFieldStrategy.java:95)
at org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:120)
at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:80)
at org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:438)
at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:403)
at org.apache.openjpa.jdbc.meta.ClassMapping.resolveMapping(ClassMapping.java:784)
at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1585)
at org.apache.openjpa.meta.MetaDataRepository.processBuffer(MetaDataRepository.java:659)
at org.apache.openjpa.meta.MetaDataRepository.resolveMapping(MetaDataRepository.java:620)
at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:498)
at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:288)
at org.apache.openjpa.kernel.TestWithListBrokerImpl.persist(TestWithListBrokerImpl.java:2352)
at org.apache.openjpa.kernel.TestWithListBrokerImpl.persist(TestWithListBrokerImpl.java:2204)
at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1010)
at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:541)
at ex9.Helper.testMappingSave(Helper.java:414)
at ex9.Helper.run(Helper.java:81)
at ex9.Helper.main(Helper.java:736)
I don't know what causes the NullPointerException but the
ArgumentException seems wrong to me. By that, I mean that my mappings
look right:
In A:
@OneToMany( mappedBy="a", fetch=FetchType.EAGER, cascade=CascadeType.ALL )
private Set<AToBMapping> bMappings;
In AToBMapping:
@Id
@ManyToOne( fetch=FetchType.EAGER, cascade=CascadeType.ALL, optional=false )
@Column( name="a_id" )
@ForeignKey
private A a;
I am still trying to find the cause for this...
Christian
On 9/6/07, Patrick Linskey <pl...@gmail.com> wrote:
> Hi,
>
> What goes into the value column?
>
> > Should I define the mapping as A (OneToMany) A_B (ManyToOne) B and
> > create an object for A_B? If so, how do I do that?
>
> You certainly could take that approach. You'd just set up a pair of
> one-to-many relations from A to A_B and B to A_B; you wouldn't need to
> do anything special to make it work.
>
> -Patrick
>
> On 9/6/07, Christian Defoy <ch...@gmail.com> wrote:
> > Hello,
> >
> > I have two objects, A and B, that are involved in a many to many
> > relationship. That portion works ok if class A contains:
> >
> > @ManyToMany( fetch=FetchType.EAGER, cascade=CascadeType.ALL )
> > @JoinTable( name="a_b", joinColumns=@JoinColumn( name="a_id",
> > referencedColumnName="a_id" ),
> > inverseJoinColumns=@JoinColumn( name="b_id",
> > referencedColumnName="b_id" ))
> > private Set<B> mappedBs;
> >
> > My problem is that the relationship between A and B must contain an
> > additional value. The join table between A and B looks like this:
> >
> > create table A_B
> > (
> > a_id integer not null,
> > b_id integer not null,
> > value integer
> > );
> >
> > Should I define the mapping as A (OneToMany) A_B (ManyToOne) B and
> > create an object for A_B? If so, how do I do that?
> >
> > Thanks in advance!
> >
> > Christian
> >
>
>
> --
> Patrick Linskey
> 202 669 5907
>
Re: Join table with extra value
Posted by Patrick Linskey <pl...@gmail.com>.
Hi,
What goes into the value column?
> Should I define the mapping as A (OneToMany) A_B (ManyToOne) B and
> create an object for A_B? If so, how do I do that?
You certainly could take that approach. You'd just set up a pair of
one-to-many relations from A to A_B and B to A_B; you wouldn't need to
do anything special to make it work.
-Patrick
On 9/6/07, Christian Defoy <ch...@gmail.com> wrote:
> Hello,
>
> I have two objects, A and B, that are involved in a many to many
> relationship. That portion works ok if class A contains:
>
> @ManyToMany( fetch=FetchType.EAGER, cascade=CascadeType.ALL )
> @JoinTable( name="a_b", joinColumns=@JoinColumn( name="a_id",
> referencedColumnName="a_id" ),
> inverseJoinColumns=@JoinColumn( name="b_id",
> referencedColumnName="b_id" ))
> private Set<B> mappedBs;
>
> My problem is that the relationship between A and B must contain an
> additional value. The join table between A and B looks like this:
>
> create table A_B
> (
> a_id integer not null,
> b_id integer not null,
> value integer
> );
>
> Should I define the mapping as A (OneToMany) A_B (ManyToOne) B and
> create an object for A_B? If so, how do I do that?
>
> Thanks in advance!
>
> Christian
>
--
Patrick Linskey
202 669 5907