You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Heather Sterling <hs...@us.ibm.com> on 2009/02/04 15:38:23 UTC

many-to-many self-referencing


Hi,

I am trying to map our current schema to JPA.  The below SoftwareModule
entity has many-to-many mappings with other entities and those are working
correctly.  However, I cannot get it to work for a self-referencing
many-to-many mapping.

JPA is not throwing any exceptions when I try to do the following.  It just
seems to completely ignore the fact that I set the targetModules.  Most of
the info I was able to dig up online showed the exact same strategy I am
already using.

1) Persist SoftwareModuleA
2) Set the target modules for SoftwareModuleB to be SoftwareModuleA and
persist SoftwareModuleB.
3) Query for SoftwareModules :

"select x from SoftwareModule x where x.targetModules is not null"  -->
returns 0 results

"select x from SoftwareModule x where x.targetModules is null" --> returns
both of the SoftwareModule's

4) The only other interesting thing of note is that this class inherits
from a base class, but I'm not sure that is playing any part in this
problem.



@Entity(name="SoftwareModule")
@Table(name="SOFTWARE_MODULE")
@PrimaryKeyJoinColumn(name="MODULE_ID", referencedColumnName="id")
public class JPASoftwareModule extends JPAManagedElement implements
Serializable {

...........

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="sftw_mod_sftw_mod_assoc",
            joinColumns=@JoinColumn(name="source_module_id"),//
referencedColumnName="module_id"),
            inverseJoinColumns=@JoinColumn(name="target_module_id"))//,
referencedColumnName="module_id"))
            private List<JPASoftwareModule> sourceModules;

    @ManyToMany(fetch=FetchType.EAGER, mappedBy="sourceModules")
    private List<JPASoftwareModule> targetModules;


Thanks

Heather Sterling
Systems Management Development
Phone:  919-254-7163 T/L: 444-7163
Cell: 919-423-3143
Email: hsterl@us.ibm.com

Re: many-to-many self-referencing

Posted by "B.J. Reed" <bj...@gmail.com>.
Hi Heather, Not seeing your calling code, I can't tell exactly what's 
wrong. I tried to stay as close to your algorithm as I could and I did 
get this to work with the following:  I'm not inheriting from another 
class and I commented out the PrimaryKeyJoinColumn and used my own int 
id.  I believe the rest of your class is unchanged.

@Entity(name="SoftwareModule")
@Table(name="SOFTWARE_MODULE")
//@PrimaryKeyJoinColumn(name="MODULE_ID", referencedColumnName="id")
public class JPASoftwareModule implements Serializable {
    @Id
    private int id;

    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="sftw_mod_sftw_mod_assoc",
            
joinColumns=@JoinColumn(name="source_module_id"),//referencedColumnName="module_id"),
            
inverseJoinColumns=@JoinColumn(name="target_module_id"))//,referencedColumnName="module_id"))
    private List<JPASoftwareModule> sourceModules;

    @ManyToMany(fetch=FetchType.EAGER, mappedBy="sourceModules")
    private List<JPASoftwareModule> targetModules;

    public JPASoftwareModule () {
        sourceModules = new ArrayList<JPASoftwareModule>();
        targetModules = new ArrayList<JPASoftwareModule>();
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getId() {
        return id;
    }
    public List<JPASoftwareModule> getSourceModules() {
        return sourceModules;
    }
    public List<JPASoftwareModule> getTargetModules() {
        return targetModules;
    }
    public String toString () {
        String buffer = "SOFTWARE MODULE";
        buffer += "\nid=" + id;
        buffer += "\nsources";
        for (int i = 0; i < sourceModules.size(); i++)
            buffer += "\n    id=" + sourceModules.get(i).getId();
        buffer += "\ntargets";
        for (int i = 0; i < targetModules.size(); i++)
            buffer += "\n    id=" + targetModules.get(i).getId();
        return buffer;
    }

my calling code:
        EntityManager em = emf.createEntityManager();

        // Create some entities
        JPASoftwareModule source1 = new JPASoftwareModule();
        source1.setId(1);

        em.getTransaction().begin();
        em.persist(source1);
        em.getTransaction().commit();
       
        JPASoftwareModule target2 = new JPASoftwareModule();
        target2.setId(2);
        JPASoftwareModule target3 = new JPASoftwareModule();
        target3.setId(3);

        source1.getSourceModules().add(target2);
        source1.getSourceModules().add(target3);
        target2.getTargetModules().add(source1);
        target3.getTargetModules().add(source1);

        em.getTransaction().begin();
        em.persist(target2);
        em.persist(target3);
        em.getTransaction().commit();

        try{
            Query q = em.createQuery("select e from SoftwareModule e 
where e.targetModules is not null");
            List<JPASoftwareModule> elist = q.getResultList();
            System.out.println("TARGET MODULES IS NOT NULL");
            for (JPASoftwareModule e : elist) {
                System.out.println(e.toString());
            }
            q = em.createQuery("select e from SoftwareModule e where 
e.targetModules is null");
            elist = q.getResultList();
            System.out.println("TARGET MODULES IS NULL");
            for (JPASoftwareModule e : elist) {
                System.out.println(e.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

I got the following output
TARGET MODULES IS NOT NULL
SOFTWARE MODULE
id=2
sources
targets
    id=1
SOFTWARE MODULE
id=3
sources
targets
    id=1
TARGET MODULES IS NULL
SOFTWARE MODULE
id=1
sources
    id=2
    id=3
targets

Let me know if this helps any.
--B.J. Reed.

Heather Sterling wrote:
> Hi,
>
> I am trying to map our current schema to JPA.  The below SoftwareModule
> entity has many-to-many mappings with other entities and those are working
> correctly.  However, I cannot get it to work for a self-referencing
> many-to-many mapping.
>
> JPA is not throwing any exceptions when I try to do the following.  It just
> seems to completely ignore the fact that I set the targetModules.  Most of
> the info I was able to dig up online showed the exact same strategy I am
> already using.
>
> 1) Persist SoftwareModuleA
> 2) Set the target modules for SoftwareModuleB to be SoftwareModuleA and
> persist SoftwareModuleB.
> 3) Query for SoftwareModules :
>
> "select x from SoftwareModule x where x.targetModules is not null"  -->
> returns 0 results
>
> "select x from SoftwareModule x where x.targetModules is null" --> returns
> both of the SoftwareModule's
>
> 4) The only other interesting thing of note is that this class inherits
> from a base class, but I'm not sure that is playing any part in this
> problem.
>
>
>
> @Entity(name="SoftwareModule")
> @Table(name="SOFTWARE_MODULE")
> @PrimaryKeyJoinColumn(name="MODULE_ID", referencedColumnName="id")
> public class JPASoftwareModule extends JPAManagedElement implements
> Serializable {
>
> ...........
>
>     @ManyToMany(fetch=FetchType.EAGER)
>     @JoinTable(name="sftw_mod_sftw_mod_assoc",
>             joinColumns=@JoinColumn(name="source_module_id"),//
> referencedColumnName="module_id"),
>             inverseJoinColumns=@JoinColumn(name="target_module_id"))//,
> referencedColumnName="module_id"))
>             private List<JPASoftwareModule> sourceModules;
>
>     @ManyToMany(fetch=FetchType.EAGER, mappedBy="sourceModules")
>     private List<JPASoftwareModule> targetModules;
>
>
> Thanks
>
> Heather Sterling
> Systems Management Development
> Phone:  919-254-7163 T/L: 444-7163
> Cell: 919-423-3143
> Email: hsterl@us.ibm.com
>