You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Jo Desmet (JIRA)" <ji...@apache.org> on 2014/11/24 10:24:12 UTC

[jira] [Updated] (OPENJPA-2546) OpenJPA using ManyToMany does not work with Set

     [ https://issues.apache.org/jira/browse/OPENJPA-2546?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jo Desmet updated OPENJPA-2546:
-------------------------------
    Description: 
Copying my own posting from StackOverflow.com

I have two Entities User and Group, having a many to many relationship. Group manages the relationship. So in Group I have:

{code:java}
@Entity 
@Table(name = "GROUPS", catalog = "", schema = "GROUPADMIN")
public class Group {
  ...
  @ManyToMany
  @JoinTable(
    name = "GROUP_USERS",
    joinColumns = {@JoinColumn(name = "GROUP_ID")},
    inverseJoinColumns = {@JoinColumn(name = "USER_ID")}
  )
  private Set<User> users;
{code}

Then for User I create the entity something as follows:

{code:java}
@Entity 
@Table(name = "USERS", catalog = "", schema = "GROUPADMIN")
public class User {
  ...
  @ManyToMany(mappedBy="users")
  private Set<Group> groups;
{code}

Then in my backing bean, actually a @Named("registry"), I store a reference to a retrieved user as a property with the same name.

Then I use that backing bean royally in my JSF

{code:html}
Hello <h:outputLabel value="#{registry.user.firstName}"/>
<h:panelGroup>
  <h:dataTable value="#{registry.user.groups}" var="g">
    <f:facet name="header">Properties List</f:facet>
    <h:column>
      <f:facet name="header">Group</f:facet>
      <h:outputText value="#{g.id}"/>
    </h:column>
  </h:dataTable>
</h:panelGroup>
{code:java}

For those interested in the tables:

{code:sql}
create table "GROUPADMIN".GROUPS
(
  ID VARCHAR(15) not null primary key
);
create table "GROUPADMIN".USERS
(
  ID VARCHAR(50) not null primary key,
  PASSWORD VARCHAR(50),
  FIRST_NAME VARCHAR(50),
  LAST_NAME VARCHAR(50)
);
create table "GROUPADMIN".GROUP_USERS
(
  GROUP_ID VARCHAR(15) not null,
  USER_ID VARCHAR(50) not null,
  primary key (GROUP_ID, USER_ID)
);
{code}

Depending on how (lazy vs Eager) and when I run it, the result would be always wrong, but sometimes different:
- sometimes complaining that property 'id' does not exist, like example below,
- sometimes the returned set was Empty (not null, but zero size).

{code}
Caused by:
javax.el.PropertyNotFoundException - Property 'id' not found on type org.apache.openjpa.util.java$util$HashSet$proxy
at javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:266)
{code}

So me being curious what I actually got into that g attribute I got from the <h:dataTable>, I tried to output it simply using {{<h:outputText value="#{g}"/>}}

What g printed out was not just one element out of the Set<Group>, but was actually the collection itself, which matches the earlier shown exception ...

One important clue is that the problem is resolved once I replace the datatype from Set<Xxx> to List<Xxx>. With that change, everything started working as expected.

However Logically wise I do need it as a Set, and the JSR documentation seems to support that.


  was:
Copying my own posting from StackOverflow.com

I have two Entities User and Group, having a many to many relationship. Group manages the relationship. So in Group I have:

{code:java}
@Entity 
@Table(name = "GROUPS", catalog = "", schema = "GROUPADMIN")
public class Group {
  ...
  @ManyToMany
  @JoinTable(
    name = "GROUP_USERS",
    joinColumns = {@JoinColumn(name = "GROUP_ID")},
    inverseJoinColumns = {@JoinColumn(name = "USER_ID")}
  )
  private Set<User> users;
{code}

Then for User I create the entity something as follows:

{code:java}
@Entity 
@Table(name = "USERS", catalog = "", schema = "GROUPADMIN")
public class User {
  ...
  @ManyToMany(mappedBy="users")
  private Set<Group> groups;
{code}

Then in my backing bean, actually a @Named("registry"), I store a reference to a retrieved user as a property with the same name.

Then I use that backing bean royally in my JSF

{code:html}
Hello <h:outputLabel value="#{registry.user.firstName}"/>
<h:panelGroup>
  <h:dataTable value="#{registry.user.groups}" var="g">
    <f:facet name="header">Properties List</f:facet>
    <h:column>
      <f:facet name="header">Group</f:facet>
      <h:outputText value="#{g.id}"/>
    </h:column>
  </h:dataTable>
</h:panelGroup>
{code:java}

For those interested in the tables:

{code:sql}
create table "GROUPADMIN".GROUPS
(
  ID VARCHAR(15) not null primary key
);
create table "GROUPADMIN".USERS
(
  ID VARCHAR(50) not null primary key,
  PASSWORD VARCHAR(50),
  FIRST_NAME VARCHAR(50),
  LAST_NAME VARCHAR(50)
);
create table "GROUPADMIN".GROUP_USERS
(
  GROUP_ID VARCHAR(15) not null,
  USER_ID VARCHAR(50) not null,
  primary key (GROUP_ID, USER_ID)
);
{code}

Depending on how (lazy vs Eager) and when I run it, the result would be always wrong, but sometimes different:
- sometimes complaining that property 'id' does not exist, like example below,
- sometimes the returned set was Empty (not null, but zero size).

{code}
Caused by:
javax.el.PropertyNotFoundException - Property 'id' not found on type org.apache.openjpa.util.java$util$HashSet$proxy
at javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:266)
{code}

So me being curious what I actually got into that g attribute I got from the <h:dataTable>, I tried to output it simply using <h:outputText value="#{g}"/> 

What g printed out was not just one element out of the Set<Group>, but was actually the collection itself, which matches the earlier shown exception ...

One important clue is that the problem is resolved once I replace the datatype from Set<Xxx> to List<Xxx>. With that change, everything started working as expected.

However Logically wise I do need it as a Set, and the JSR documentation seems to support that.



> OpenJPA using ManyToMany does not work with Set<xxx>
> ----------------------------------------------------
>
>                 Key: OPENJPA-2546
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-2546
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: instrumentation, jpa
>    Affects Versions: 2.4.0
>         Environment: Running as part of TomEE 1.7.1
>            Reporter: Jo Desmet
>              Labels: @ManyToMany, bidirectional
>
> Copying my own posting from StackOverflow.com
> I have two Entities User and Group, having a many to many relationship. Group manages the relationship. So in Group I have:
> {code:java}
> @Entity 
> @Table(name = "GROUPS", catalog = "", schema = "GROUPADMIN")
> public class Group {
>   ...
>   @ManyToMany
>   @JoinTable(
>     name = "GROUP_USERS",
>     joinColumns = {@JoinColumn(name = "GROUP_ID")},
>     inverseJoinColumns = {@JoinColumn(name = "USER_ID")}
>   )
>   private Set<User> users;
> {code}
> Then for User I create the entity something as follows:
> {code:java}
> @Entity 
> @Table(name = "USERS", catalog = "", schema = "GROUPADMIN")
> public class User {
>   ...
>   @ManyToMany(mappedBy="users")
>   private Set<Group> groups;
> {code}
> Then in my backing bean, actually a @Named("registry"), I store a reference to a retrieved user as a property with the same name.
> Then I use that backing bean royally in my JSF
> {code:html}
> Hello <h:outputLabel value="#{registry.user.firstName}"/>
> <h:panelGroup>
>   <h:dataTable value="#{registry.user.groups}" var="g">
>     <f:facet name="header">Properties List</f:facet>
>     <h:column>
>       <f:facet name="header">Group</f:facet>
>       <h:outputText value="#{g.id}"/>
>     </h:column>
>   </h:dataTable>
> </h:panelGroup>
> {code:java}
> For those interested in the tables:
> {code:sql}
> create table "GROUPADMIN".GROUPS
> (
>   ID VARCHAR(15) not null primary key
> );
> create table "GROUPADMIN".USERS
> (
>   ID VARCHAR(50) not null primary key,
>   PASSWORD VARCHAR(50),
>   FIRST_NAME VARCHAR(50),
>   LAST_NAME VARCHAR(50)
> );
> create table "GROUPADMIN".GROUP_USERS
> (
>   GROUP_ID VARCHAR(15) not null,
>   USER_ID VARCHAR(50) not null,
>   primary key (GROUP_ID, USER_ID)
> );
> {code}
> Depending on how (lazy vs Eager) and when I run it, the result would be always wrong, but sometimes different:
> - sometimes complaining that property 'id' does not exist, like example below,
> - sometimes the returned set was Empty (not null, but zero size).
> {code}
> Caused by:
> javax.el.PropertyNotFoundException - Property 'id' not found on type org.apache.openjpa.util.java$util$HashSet$proxy
> at javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:266)
> {code}
> So me being curious what I actually got into that g attribute I got from the <h:dataTable>, I tried to output it simply using {{<h:outputText value="#{g}"/>}}
> What g printed out was not just one element out of the Set<Group>, but was actually the collection itself, which matches the earlier shown exception ...
> One important clue is that the problem is resolved once I replace the datatype from Set<Xxx> to List<Xxx>. With that change, everything started working as expected.
> However Logically wise I do need it as a Set, and the JSR documentation seems to support that.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)