-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Criteria and ManyToMany queries
PostPosted: Tue Aug 03, 2010 2:22 pm 
Newbie

Joined: Tue Aug 03, 2010 2:13 pm
Posts: 2
Given this schema:

Table 'A':
int A_ID primary key;
varchar name;

Table 'B':
int B_ID primary key;
varchar name;

Table 'A_B':
int A_ID not null foreign key(A);
int B_ID not null foreign key(B);

Then A is tied to B with this annotation defined in A.java:

Code:
    @ManyToMany()
    @JoinTable (
        name = "A_B",
        joinColumns = @JoinColumn(name = "A_ID"),
        inverseJoinColumns = @JoinColumn(name = "B_ID")
    )
    /** properties */
    private Collection<Property> bees = null;


The reverse tie is done in B as well (although this shouldn't matter). How can I use the Criteria API to generate this query for A objects?

Code:
select A.*
  from A as X
inner join A_B as Y on (X.A_ID = Y.A_ID)
inner join B as Z on (Y.B_ID = Z.B_ID)
where Z.name in ('Moo', 'Bark', 'Meow')


I've tried several stabs, the most recent being:

List<B> bees = session.createCriteria(B.class)
.add(Restrictions.in("name", [list of 'Moo', 'Bark', 'Meow'])
.list();
Criteria c = session.createCriteria(A.class)
.add(Restrictions.in("bees", bees));

To no avail.

Also, are there any in-depth books on the Criteria API?


Top
 Profile  
 
 Post subject: Re: Criteria and ManyToMany queries
PostPosted: Wed Aug 04, 2010 12:33 pm 
Newbie

Joined: Tue Aug 03, 2010 2:13 pm
Posts: 2
I finally figured out how to do this, and thought I'd pass along my solution for anyone who finds this post in the future. First of all, I was using an older version of Hibernate (3.2) that did not support nesting DetachedCriteria (threw NullPointExceptions in getTypes() from the SQL builders). Version 3.5.4 works just fine with something like this:

Code:
        // listOfBees is a List<B> containing 'Moo', 'Bark, 'Meow'       
        List<Integer> bids = new ArrayList<Integer>(listOfBees.size());
        for (B b : listOfBees)
             bids.add(b.getID());
        DetachedCriteria detached = DetachedCriteria.forClass(A.class)
            .createAlias("bees", "bees")
            .setProjection(Projections.id())
            .add(Subqueries.propertyIn("bees.id",
                DetachedCriteria.forClass(B.class, "bPrime")
                    .setProjection(Projections.id())
                    .add(Restrictions.in("bPrime.ID", bids))));
        Criteria c = s.createCriteria(A.class, "A");
        c.add(Subqueries.propertyIn("A.id", detached));
        c.list();


Which will generate SQL that looks somewhat like this:

Code:

select A.*
   from A as X
where A_ID in
   (select A_ID
      from A inner join A_B inner join B
   where B.ID in
      (select B_ID
         from B
      where B_ID in (1, 2, 3)
      )
   )



It would be nice to use B objects directly instead if converting them to IDs first, but I cannot see how that is possible because the only Projection that makes sense for this task is the id() one. If anyone has a way around that, it would be great.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.