persistence@glassfish.java.net

Re: Problem using ManyToMany relationship

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Wed, 28 Mar 2007 13:33:50 -0700

Hi Tim,

Romanowski, Tim wrote:
> Hi Marina,
> I was only using AtrributeOverride based on another example I found while
> googling a couple months ago; I forget what the reasoning was, but I looked
> at the spec, agreed with the example writers explanation, and moreso, found
> that it allowed me to compile & deploy my app. In hindsight, I have to
> assume that I changed more than one thing at a time and attributed the "fix"
> to the wrong code. As I mentioned in my last e-mail, I removed
> @AttributeOverride a couple hours ago, and it did not appear to affect my
> app in anyway, so all I can plead is insanity =)
>
> So, where does that leave me? With a couple questions:
>
> 1) In the newer code I posted below, is there an obvious reason why
> NetBeans would be reporting:
>
> "Inconsistent access type in entity class because a field in this class or
> its super class chain is already annotated as @Id or @EmbeddedId."

@Id or @EmbeddedId are the annotations that define access type (because either
one is required in entity that uses annotations). Which means that if there are
annotations that are also placed on a getter as in your example below, it's an
error.

>
> I do not see how this "inconsistent access type" is even relevant...I am
> annotating the getter of a field, and that field is NOT the id of the entity
> (in this case, entity Team).

While it's probably doable to have mixed annotations, it's not supported by the
spec, so there is no requirement for the persistence providers to support it either.

>
>
> 2) How do I annotate my userCollection field in the Team entity, instead of
> the getUserCollection method in that same entity? If do so with this:
> @ManyToMany
> @JoinTable(name = "team_users",
> joinColumns = {_at_JoinColumn(name = "teamid", referencedColumnName =
> "teamid")},
> inverseJoinColumns = {_at_JoinColumn(name = "username",
> referencedColumnName = "username")})
> private java.util.Collection <com.lmco.gems.persistence.entity.Users>
> userCollection;

The annotation on the field or property should be the same.

The exception below comes from a query - can you post it here?

thanks,
-marina

>
> I get this:
> Local Exception Stack:
> Exception [TOPLINK-6094] (Oracle TopLink Essentials - 2.0 (Build b40-rc
> (03/20/2007))): oracle.toplink.essentials.exceptions.QueryException
> Exception Description: The parameter name [username] in the query's
> selection criteria does not match any parameter name defined in the query.
> Query: ReadAllQuery(com.lmco.gems.persistence.entity.Team)
> at
> oracle.toplink.essentials.exceptions.QueryException.parameterNameMismatch(Qu
> eryException.java:966)
> at
> oracle.toplink.essentials.internal.expressions.ParameterExpression.getValue(
> ParameterExpression.java:215)
> at
> oracle.toplink.essentials.internal.databaseaccess.DatabaseCall.translate(Dat
> abaseCall.java:821)
> at
> oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechani
> sm.executeCall(DatasourceCallQueryMechanism.java:212)
>
>
>
> -----Original Message-----
> From: Marina.Vatkina_at_Sun.COM [mailto:Marina.Vatkina_at_Sun.COM]
> Sent: Wednesday, March 28, 2007 4:02 PM
> To: persistence_at_glassfish.dev.java.net
> Subject: Re: Problem using ManyToMany relationship
>
> Tim,
>
> All annotations should be placed in a similar way - either on the fields or
> on
> the properties (i.e. getters). The current spec doesn't allow to mix them
> not
> only in the same class, but even in an inheritance hierarchy.
>
> Why do you need to use @AttributeOverride? Here is what the spec says:
>
> 9.1.10 AttributeOverride Annotation
>
> The AttributeOverride annotation is used to override the mapping of a Basic
> (whether explicit or default) property or field or Id property or field. The
>
> AttributeOverride annotation may be applied to an entity that extends a
> mapped
> superclass or to an embedded field or property to override a basic mapping
> defined by the mapped superclass or embeddable class.
>
> Regards,
> -marina
>
> Romanowski, Tim wrote:
>
>>Markus, thanks for the response; hopefully I can provide you enough info
>>to help me. When you said "Please note that you can't have both field-
>>and property-based access in the same entity (Your example shows the Id
>>annotation on the field, and you mention annotating the getter method)",
>>I'm not sure I understand._at_Id is for my Team entity is on the field
>>"teamid". The method I annotated (getUserCollection) refers to the
>>userCollection field, not the teamid field. Is there something I'm not
>>seeing? Perhaps you are referring to the @Id for the username field in
>>the Users entity? If so, why does it matter that the getter of Users in
>>another class (Team entity) is disallowed to have the below annotation?
>> I can't post all the code in the classes, but I can post most of it;
>>here's the code again, formatted a little better.
>>
>>
>>
>>My preference is to only annotate fields, not methods, but that failed
>>to compile for me. I did just now remove the @AttributeOverride and
>>that did not cause any noticeable issues. Obviously, I'm not sure what
>>I'm doing-I was following the spec, but had some odd behavior, so I
>>began reading various web articles and ManyToMany examples.eventually
>>settling on the code below, which was the only code I found to 'work,'
>>in the sense that it would at least compile and deploy. Any further
>>comments are fully welcome!
>>
>>
>>
>>
>>
>>@Entity
>>
>>@Table(name = "TEAM")
>>
>>public class Team implements Serializable {
>>
>>
>>
>> @SequenceGenerator(sequenceName="seq_teamid", name="teamid_gen",
>>initialValue=1, allocationSize=1)
>>
>>
>>
>> @Id @GeneratedValue(generator="teamid_gen")
>>
>> @Column(name = "TEAMID", nullable = false)
>>
>> private BigDecimal teamid;
>>
>>
>>
>>@ManyToMany
>>
>> private java.util.Collection <com.my.persistence.entity.Users>
>>userCollection;
>>
>>
>>
>>
>>
>> @ManyToMany
>>
>> @JoinTable(name = "team_users",
>>
>> joinColumns = {_at_JoinColumn(name = "teamid", referencedColumnName
>>= "teamid")},
>>
>> inverseJoinColumns = {_at_JoinColumn(name = "username",
>>referencedColumnName = "username")})
>>
>> public java.util.Collection<com.my.persistence.entity.Users>
>>getUserCollection() {
>>
>> return userCollection;
>>
>> }
>>
>>
>>
>> public void
>>setUserCollection(java.util.Collection<com.my.persistence.entity.Users>
>>userCollection) {
>>
>> this.userCollection = userCollection;
>>
>> }
>>
>>} // End class Team
>>
>>
>>
>>
>>
>>@Entity
>>
>>@Table(name = "USERS")
>>
>>public class Users implements Serializable {
>>
>>
>>
>> @Id
>>
>> @Column(name = "USERNAME", nullable = false)
>>
>> private String username;
>>
>>
>>
>> @ManyToMany(mappedBy="userCollection")
>>
>> @AttributeOverride(name="teamCollection",
>
> column=_at_Column(name="teamid"))
>
>> private java.util.Collection <com.my.persistence.entity.Team>
>>teamCollection;
>>
>>
>>
>>
>>
>> public java.util.Collection <com.my.persistence.entity.Team>
>>getTeamCollection() {
>>
>> return this.teamCollection;
>>
>> }
>>
>>
>>
>> public void setTeamCollection(java.util.Collection
>><com.my.persistence.entity.Team> teamCollection) {
>>
>> this.teamCollection = teamCollection;
>>
>> }
>>
>>}
>>
>>
>>
>>
>>
>>
>>
>>------------------------------------------------------------------------
>>
>>*From:* Markus.Fuchs_at_Sun.COM [mailto:Markus.Fuchs_at_Sun.COM]
>>*Sent:* Monday, March 26, 2007 5:44 PM
>>*To:* persistence_at_glassfish.dev.java.net
>>*Subject:* Re: Problem using ManyToMany relationship
>>
>>
>>
>>Hi Tim,
>>
>>Romanowski, Tim wrote:
>>
>>Tricky problem I thought I solved, and I hope someone could explain to
>>me both 1) why this kind of works, and 2) why it doesn't completely work.
>>
>>
>>
>>Situation: I have a ManyToMany relationship between two entities, Team
>>and User. A team has many users and a user has many teams. I have a
>>join table called team_users which contains two fields: teamid and
>>username, which map to the corresponding primary keys of the Team and
>>User tables.
>>
>>
>>
>>Problem: Creating a 'standard' ManyToMany relationship where I pick an
>>arbitrary owning entity and annotate a member variable (rather than its
>>get method) does not work. The only way for me to compile and deploy my
>>webapp is to annotate these two entities as you see below.
>>
>>
>>
>>Questions:
>>
>>In the Team entity, why doest the @JoinTable annotation on the
>>getUserCollection method work, but not work if I instead place that same
>>annotation on the userCollection property?
>>
>>Both ways should work. Please note that you can't have both field- and
>>property-based access in the same entity (Your example shows the Id
>>annotation on the field, and you mention annotating the getter method)
>>
>>In the User entity, why must I use the @AttributeOverride annotation on
>>the teamCollection property?
>>
>>No annotation besides "mappedBy" should be used on the non-owning side.
>>The AttributeOverwrite must not be used.
>>
>>Could you please send me your the Team and User classes?
>>
>>Thanks,
>>
>>-- markus.
>>