-->
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.  [ 14 posts ] 
Author Message
 Post subject: Filter() on composite-element's -- possible?
PostPosted: Sun Oct 19, 2003 8:55 am 
Newbie

Joined: Thu Oct 16, 2003 7:22 pm
Posts: 12
I am evaluating Hibernate for a project, and have been stuck on this problem for a few days - any help would be greatly appreciated...

Is it possible to use Session.filter() on a collection of composite-element's?

If I try to do this, I get a QueryException:

Quote:
java.lang.RuntimeException: net.sf.hibernate.QueryException: collection of values in filter: this [null]


looking at QueryTranslator.java, it looks like it's barfing because the collection elements are not entity objects? Is this correct? I can find no mention of this anywhere in the docs...

daniel


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 19, 2003 9:43 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Yeah, this is not yet possible, but is probably not very difficult to implement in 2.1. Its an obvious extension that I already have on my list. Add it to JIRA as a feature request if you like.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 12, 2003 8:34 pm 
Newbie

Joined: Mon Oct 06, 2003 4:41 pm
Posts: 18
I've raised this as HB-467. It would be really useful to be able to do:

int count = ((Integer) session.filter(myCompositeElementsCollection, "select count(*) where myProperty = ?", somePropertyValue, Hibernate.entity(SomePropertyType.class)).iterator().next()).intValue();

Does anyone know a work-around in the meantime?

Thanks,
Matt.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 12, 2003 9:43 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Just use an ordinary query (filters can always be rewritten as queries)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 16, 2003 5:47 pm 
Newbie

Joined: Mon Oct 06, 2003 4:41 pm
Posts: 18
Ok, I'm sure you're right but I'm not getting anywhere. My attempt at rewriting my previous example as an ordinary query is looking like this:

Code:
Query query = session.createQuery("select count(*) from SomeElement as se where se.myProperty = :someVal");
query.setParameter("someVal", someVal);


where SomeElement is a POJO and myProperty is a many-to-many association to the same POJO using a composite element defined as follows:

Code:
<set
  name="myProperty"
  table="HIBERNATE_MY_PROPERTY"
  lazy="true"
  inverse="false"
  cascade="all"
  sort="unsorted"
  order-by="date"
>
  <key
    column="SomeElement_id"
  />

  <composite-element
    class="SomeElement"
  >
    <property
      name="date"
      type="java.util.Date"
      update="true"
      insert="true"
      column="date"
    />
    <many-to-one
      name="parent"
      class="SomeElement"
      cascade="save-update"
      outer-join="auto"
      update="true"
      insert="true"
      column="parent_id"
      not-null="true"
    />
  </composite-element>
</set>


When I run my code I get this:
Code:
net.sf.hibernate.QueryException: unindexed collection before []: someelem0_.myProperty [select count(*) from SomeElement as se where se.myProperty = :someVal]
   at net.sf.hibernate.hql.PathExpressionParser.prepareForIndex(PathExpressionParser.java:301)
   at net.sf.hibernate.hql.PathExpressionParser.end(PathExpressionParser.java:285)
   at net.sf.hibernate.hql.WhereParser.doPathExpression(WhereParser.java:335)
   at net.sf.hibernate.hql.WhereParser.doToken(WhereParser.java:365)
   at net.sf.hibernate.hql.WhereParser.token(WhereParser.java:250)
   at net.sf.hibernate.hql.ClauseParser.token(ClauseParser.java:87)
   at net.sf.hibernate.hql.PreprocessingParser.token(PreprocessingParser.java:123)
   at net.sf.hibernate.hql.ParserHelper.parse(ParserHelper.java:29)
   at net.sf.hibernate.hql.QueryTranslator.compile(QueryTranslator.java:151)
   at net.sf.hibernate.hql.QueryTranslator.compile(QueryTranslator.java:140)
   at net.sf.hibernate.impl.SessionFactoryImpl.getQuery(SessionFactoryImpl.java:291)
   at net.sf.hibernate.impl.SessionImpl.getQueries(SessionImpl.java:1501)
   at net.sf.hibernate.impl.SessionImpl.iterate(SessionImpl.java:1531)
   at net.sf.hibernate.impl.QueryImpl.iterate(QueryImpl.java:33)


I can't find anything in the documentation that says this can't work on a Set. What am I doing wrong?

Matt.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 16, 2003 10:12 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Hmmm. Actually you're right. Theres no way to do this efficiently at present. You would have to use:

Code:
select count(*) from Parent p
join p.myProperty elem
where p.id = :pid



Which involves a join that is unnecessary. I forgot that there was a case for collection filters! OK, a agree we should make this work ASAP.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 17, 2003 5:54 pm 
Newbie

Joined: Mon Oct 06, 2003 4:41 pm
Posts: 18
So if I wanted something more like this where the criteria is actually on a property of the association class rather than on the parent class. I.e. in my example I want a count of the number of many to many associations between Parent and whatever it's related to where the assocationClass.someProperty = someValue...

Code:
select count(ac) from Parent p join p.associationClass ac where ac.someProperty = :someValue


... would you expect it work as 2.1b6 stands today? I get the following:

Code:
net.sf.hibernate.QueryException: could not resolve property: id of: ...
at net.sf.hibernate.persister.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:35)
at net.sf.hibernate.collection.AbstractCollectionPersister.toType(AbstractCollectionPersister.java:701)


Of course the assocationClass, a composite-element, doesn't have an id. Should it?

Seeing as I have a work-around would it be better just to just wait until the enhancement is implemented as this behaviour will then be irrelevant?

Matt.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 17, 2003 7:29 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Ummmm ... wtf is "associationClass"?? You should be using the name of a collection role there. "associationClass" does not sound like the name of a collection. Mapping?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 17, 2003 8:11 pm 
Newbie

Joined: Mon Oct 06, 2003 4:41 pm
Posts: 18
Sorry, I'm getting mixed up wth my examples. Here's the the real mapping which might make things clearer. The example is based on players (example.PlayerInGame) that can "attack" other players, so there's a many-to-many relationship. I want to express the fact that the association contains a property of "attackDate" indicating when the attack happened and I'm doing this with a composite-element.

Code:
    <class
        name="example.PlayerInGame"
        table="HIBERNATE_PLAYER_IN_GAME"
        proxy="example.PlayerInGame"
        dynamic-update="false"
        dynamic-insert="false">
        <id
            name="playerInGameId"
            column="player_in_game_id"
            type="long"
            unsaved-value="0">
            <generator class="increment" />
        </id>
        <set
            name="attackDetails"
            table="HIBERNATE_ATTACK_DETAILS"
            lazy="true"
            inverse="false"
            cascade="all"
            sort="unsorted"
            order-by="attackDate">
              <key column="player_in_game_id" />
              <composite-element class="example.AttackDetails">
                <property
                    name="attackDate"
                    type="java.util.Date"
                    update="true"
                    insert="true"
                    column="attackDate" />
                <many-to-one
                    name="attacker"
                    class="example.PlayerInGame"
                    cascade="save-update"
                    outer-join="auto"
                    update="true"
                    insert="true"
                    column="attacked_by_id"
                    not-null="true" />
              </composite-element>
        </set>
    </class>


My HQL should tell me how many times a defender has been attacked by an attacker (hopefully explains my original need to filter).

This is where I'm at with my HQL which gives the error I mentioned in my last post:

Code:
select count(ad) from PlayerInGame defender join defender.attackDetails ad where ad.attacker = :attacker and defender = :defender


I hope this makes more sense rather than less. Thanks for your time!

Matt.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 17, 2003 8:14 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
This should work just fine in 2.1 (in fact, I'm quite certain that it does).


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 17, 2003 8:42 pm 
Newbie

Joined: Mon Oct 06, 2003 4:41 pm
Posts: 18
Well, hmm... not sure where to go from here. This problem is most definitely happening and I can't think of much else that I could be doing wrong, except...

My hibernate output shows this:
Code:
00:23:08,529  INFO net.sf.hibernate.cfg.Environment - Hibernate 2.1 beta 5


Even though the readme.txt in my hibernate distribution shows this:
Code:
version 2.1 beta 6, 5 November 2003


And I didn't download beta 5, so there's no way I could be running against beta 5.

Here's my log & stack trace, I don't really understand why it's looking for an id on a composite-element, should I have one?

Code:
00:29:08,326 DEBUG net.sf.hibernate.impl.SessionImpl - iterate: select count(ad) from PlayerInGame defender join defender.attackDetails ad where ad.attacker = :attacker and defender = :defender
00:29:08,326 DEBUG net.sf.hibernate.engine.QueryParameters - named parameters: {defender=PlayerInGame#4, attacker=PlayerInGame#3}
00:29:08,336 DEBUG net.sf.hibernate.hql.QueryTranslator - compiling query
00:29:08,336 ERROR example.PlayerInGame - Exception during getNumAttacksBy()
net.sf.hibernate.QueryException: could not resolve property: id of: example.AttackDetails [select count(ad) from example.PlayerInGame defender join defender.attackDetails ad where ad.attacker = :attacker and defender = :defender]
   at net.sf.hibernate.persister.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:35)
   at net.sf.hibernate.collection.AbstractCollectionPersister.toType(AbstractCollectionPersister.java:701)
   at net.sf.hibernate.hql.PathExpressionParser.getPropertyType(PathExpressionParser.java:242)
   at net.sf.hibernate.hql.PathExpressionParser.end(PathExpressionParser.java:281)
   at net.sf.hibernate.hql.ParserHelper.parse(ParserHelper.java:30)
   at net.sf.hibernate.hql.SelectParser.token(SelectParser.java:140)
   at net.sf.hibernate.hql.ClauseParser.token(ClauseParser.java:87)
   at net.sf.hibernate.hql.ClauseParser.end(ClauseParser.java:114)
   at net.sf.hibernate.hql.PreprocessingParser.end(PreprocessingParser.java:143)
   at net.sf.hibernate.hql.ParserHelper.parse(ParserHelper.java:30)
   at net.sf.hibernate.hql.QueryTranslator.compile(QueryTranslator.java:151)
   at net.sf.hibernate.hql.QueryTranslator.compile(QueryTranslator.java:140)
   at net.sf.hibernate.impl.SessionFactoryImpl.getQuery(SessionFactoryImpl.java:291)
   at net.sf.hibernate.impl.SessionImpl.getQueries(SessionImpl.java:1501)
   at net.sf.hibernate.impl.SessionImpl.iterate(SessionImpl.java:1531)
   at net.sf.hibernate.impl.QueryImpl.iterate(QueryImpl.java:33)
   at example.PlayerInGame.getNumAttacksOn(PlayerInGame.java:459)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 18, 2003 2:32 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Well, submit a test to JIRA. Make sure it is very simple and runs and fails immediately. TIA.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 02, 2003 6:57 pm 
Newbie

Joined: Mon Oct 06, 2003 4:41 pm
Posts: 18
For anyone that finds this thread, see JIRA issue:
http://opensource.atlassian.com/projects/hibernate/secure/ViewIssue.jspa?key=HB-513

The solution is to be found in in section 10.7 of the documentation:

Quote:
Never try to use a path-expression that ends in a property of component type (as opposed to a property of a component).


My query should read:

Code:
select count(*) from PlayerInGame defender join defender.attackDetails ad where ad.attacker = :attacker and defender = :defender


... note the count(*) instead of count(ad).

Rather a lot of time for such an easy to implement solution but just think how much I learnt in the process!

Matt.


Top
 Profile  
 
 Post subject: Re: Filter() on composite-element's -- possible?
PostPosted: Fri Jun 25, 2010 11:03 am 
Newbie

Joined: Wed Jan 30, 2008 6:40 pm
Posts: 3
sorry about reopen this topic but i search and not found actual information, how is the issue about filter collection with composite items? i try this :

Code:
newSession.createFilter(aplicativo.getLiberadores(), "where this.activo = :activo").setString("activo", activo).list();


aplicativo is a Entity Object with a Component Collection used in a Many to Many association between Aplicativos and Empleado entities ( component class have extra filed to active status )

when execute the query i have this exception
Code:
org.hibernate.QueryException: collection of values in filter: this [where this.activo= :activo]


here my entities

Aplicativos.java
Code:
package domain;

import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;

import org.hibernate.annotations.CollectionOfElements;

@Entity
public class Aplicativos {
   private String idAplicativo;
   private String aplicativo;
   private String activo;
   private List <LiberadorContrata> liberadores = new ArrayList<LiberadorContrata>();

   public Aplicativos(){
      super();
   }
   
   
   @Id
   public String getIdAplicativo() {
      return idAplicativo;
   }
   public void setIdAplicativo(String idAplicativo) {
      this.idAplicativo = idAplicativo;
   }
   public String getAplicativo() {
      return aplicativo;
   }
   public void setAplicativo(String aplicativo) {
      this.aplicativo = aplicativo;
   }
   
   public String getActivo() {
      return activo;
   }
   public void setActivo(String activo) {
      this.activo = activo;
   }
   
   @CollectionOfElements(fetch = FetchType.EAGER)
   @JoinTable (name="ContratasLiberador", joinColumns = @JoinColumn(name = "idAplicativo"))
   public List<LiberadorContrata> getLiberadores() {
      return liberadores;
   }

   public void setLiberadores(List<LiberadorContrata> liberadores) {
      this.liberadores = liberadores;
   }

}


Liberadores.java
Code:
package domain;

import javax.persistence.*;

import org.hibernate.annotations.Parent;

@Embeddable
public class LiberadorContrata {
   
   private Aplicativos aplicativo;
   private Empleado empleado;
   private String activo;
   
   @Parent
   public Aplicativos getAplicativo() {
      return aplicativo;
   }

   public void setAplicativo(Aplicativos aplicativo) {
      this.aplicativo = aplicativo;
   }

   @ManyToOne
   @JoinColumn(name = "idEmpleado", nullable= false, updatable= false)
   public Empleado getEmpleado() {
      return empleado;
   }
   
   public void setEmpleado(Empleado empleado) {
      this.empleado = empleado;
   }
   
   @Column
   public String getActivo() {
      return activo;
   }
   
   public void setActivo(String activo) {
      this.activo = activo;
   }
   
}


i think move LiberadoresContrata composite class to intermediate entity but i dont like that approach with composite primary key; composite value type is more elegant to my case. i think.

regards

Grubhart


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 14 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.