-->
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.  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: How to put sort comparator in a mapping file...
PostPosted: Thu Jul 14, 2005 4:48 pm 
Newbie

Joined: Thu Jul 14, 2005 4:29 pm
Posts: 6
Location: Canada
Hello everyone,

I have some POJOs that have static custom comparator classes inside them. I keep the comparator classes inside the POJOs so that they are easily accessible. (I just send Staff.NameComparator() as the comparator when I call sort() on a List). (See this for a better description of what I have. How can I specify the comparator class as a sort attribute to a <set> tag in a mapping file?

in package myapp.model
Code:
class Staff {
  ...
  public static Comparator NameComparator = new Comparator() {
    ...
  }
}


I need to specify this static comparator class in a mapping file.
Code:
<set ...
  sort="what_goes_here?"
  ...
>


I have tried myapp.model.Staff.NameComparator and myapp.model.NameComparator. The error I get is org.hibernate.MappingException: Could not instantiate comparator class:

Is it possible to specify such a mapping or do I have to pull all the comparators out of the Staff class and put them in a util class (ugh, more files). I would like to have Hibernate auto-sort the List if possible.

Sorry this is so terse. TIA,
graham.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 14, 2005 6:47 pm 
Regular
Regular

Joined: Thu May 26, 2005 12:20 am
Posts: 72
try myapp.model.Staff$NameComparator


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 12:53 pm 
Newbie

Joined: Thu Jul 14, 2005 4:29 pm
Posts: 6
Location: Canada
dslevine wrote:
try myapp.model.Staff$NameComparator


Thanks for the try. That doesn't seem to work, I'm afraid. Same error as before.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 1:44 pm 
Senior
Senior

Joined: Tue Jun 21, 2005 10:18 am
Posts: 135
Location: South Carolina, USA
Could you post a short version of your myapp.model.Staff class (short meaning cut out most of the vanilla implementing code and let us have a look at the structure)?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 1:47 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
Caulfield14 wrote:
dslevine wrote:
try myapp.model.Staff$NameComparator


Thanks for the try. That doesn't seem to work, I'm afraid. Same error as before.


I think the key is in the error message. Hibernate is trying to Instantiate your comparator class. And the way you have it defined, that's not possible.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 1:48 pm 
Regular
Regular

Joined: Thu May 26, 2005 12:20 am
Posts: 72
also, try turning on debug logging and see if anything interesting comes out about what it is trying to parse and load.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 1:50 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
pksiv wrote:
Caulfield14 wrote:
dslevine wrote:
try myapp.model.Staff$NameComparator


Thanks for the try. That doesn't seem to work, I'm afraid. Same error as before.


I think the key is in the error message. Hibernate is trying to Instantiate your comparator class. And the way you have it defined, that's not possible.


I think you would need to define it like

Code:
class Staff {
  ...
  public static class NameComparator implements Comparator {
    ... Comparator implementation goes here.
  }
}


And even then Hibernate might have a problem with it being static.


Top
 Profile  
 
 Post subject: Code sample, and a question to everyone else out there...
PostPosted: Fri Jul 15, 2005 3:33 pm 
Newbie

Joined: Thu Jul 14, 2005 4:29 pm
Posts: 6
Location: Canada
eagle79 wrote:
Could you post a short version of your myapp.model.Staff class (short meaning cut out most of the vanilla implementing code and let us have a look at the structure)?


Ok, here goes:
Code:
package myApp.model;
      
import java.io.Serializable;
import java.util.*;

public class Staff implements Serializable, Comparable {

   public Staff() {}

   private Integer id;
   public Integer getId() {
   public void setId(Integer id) {

   private String userName;
   public String getUserName() {
   public void setUserName(String userName) {

   private Collection<Role> roles;
   public Collection<Role> getRoles() {
   public void setRoles(Collection roles) {
   public void addRole(Role role) {


   public boolean equals(Object o) {
      if (this == o) return true;
      if (!(o instanceof Staff)) return false;
      final Staff staff = (Staff) o;
      if (!userName.equals(staff.userName)) return false;
      return true;
   }

   public String toString() {
      return  "Staff ('" + getId() + "'), " +
            "Username: '" + getUserName() + "'";
   }

   // The natural comparator works with the Staff ID
   public int compareTo(Object anotherStaff) throws ClassCastException {
      if (!(anotherStaff instanceof Staff))
         throw new ClassCastException("A Staff object expected.");
      int anotherStaffId= ((Staff) anotherStaff).getId(); 
      return this.id - anotherStaffId;   
   }

   // I would like to include other Comparator classes directly in this class, since the Comparators will serve no purpose to any other classes.
   public class NameComparator implements Comparator {
      public int compare(Object staff, Object anotherStaff) {
         String name= ((Staff) staff).getUserName().toUpperCase();
         String anotherName= ((Staff) anotherStaff).getUserName().toUpperCase();

         return name.compareTo(anotherName);
      }      
   }

}


Now, I have also tried making the NameComparator class a static property of the Staff class, like this:

Code:
   public static Comparator NameComparator = new Comparator() {
      public int compare(Object staff, Object anotherStaff) {
   ...


...and that hasn't worked either.

Using the first method, I have actually run getCanonicalName() on the NameComparator class object and recieved myApp.model.Staff.NameComparator, which would lead me to believe I could enter that into the sort attribute and Hibernate would be able to find that comparator class. Alas, no.

How is everyone else implementing their custom comparator classes? (sorry about that icky alliteration :) Is everyone putting them in their own seperate classes (ie: in a different .java file possibly in a different package)? Doesn't this add a lot bloat? Wouldn't it be better to put that code directly into the class that it does sorting on, thus keeping it handy? I would really appreciate hearing how others handle this. Does anyone have some "best practices" advice on this?

Thanks again, IA
graham.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 3:36 pm 
Newbie

Joined: Thu Jul 14, 2005 4:29 pm
Posts: 6
Location: Canada
dslevine wrote:
also, try turning on debug logging and see if anything interesting comes out about what it is trying to parse and load.


Unfortunately, it doesn't say much. If I simply remove the sort attribute from the mapping file, everything works (albeit unsorted). Everything seems to work just dandy until it tries to instantiate the comparator class, which it can't find, and then gives the error posted earlier.

graham.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 3:40 pm 
Newbie

Joined: Thu Jul 14, 2005 4:29 pm
Posts: 6
Location: Canada
pksiv wrote:

I think you would need to define it like

Code:
class Staff {
  ...
  public static class NameComparator implements Comparator {
    ... Comparator implementation goes here.
  }
}


And even then Hibernate might have a problem with it being static.

Yeah, I think it does. How would you handle these Comparator classes? Would you just throw them in their own .java file and save all this hassle?

g.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 3:43 pm 
Regular
Regular

Joined: Thu May 26, 2005 12:20 am
Posts: 72
pksiv was correct in his reply a few ago, about needed to create an inner class, not a field. i didnt read your example close enough. try that, it should work. I would thinkin that case you might want myapp.model.Staff$NameComparator or myapp.model.Staff.NameComparator


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 15, 2005 3:54 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
Caulfield14 wrote:
pksiv wrote:

I think you would need to define it like

Code:
class Staff {
  ...
  public static class NameComparator implements Comparator {
    ... Comparator implementation goes here.
  }
}


And even then Hibernate might have a problem with it being static.

Yeah, I think it does. How would you handle these Comparator classes? Would you just throw them in their own .java file and save all this hassle?

g.


The few times that I've needed more than 1 way to compare on object, I did put the Comparator class in it's own file.


Top
 Profile  
 
 Post subject: SUCCESS!!!
PostPosted: Fri Jul 15, 2005 4:12 pm 
Newbie

Joined: Thu Jul 14, 2005 4:29 pm
Posts: 6
Location: Canada
dslevine wrote:
pksiv was correct in his reply a few ago, about needed to create an inner class, not a field. i didnt read your example close enough. try that, it should work. I would thinkin that case you might want myapp.model.Staff$NameComparator or myapp.model.Staff.NameComparator


Finally!

Yes, it does require the myApp.model.Staff$NameComparator naming method.

Some things I've learned:
    The Comparator class must be an inner class, not a class variable
    The Comparator class must be static. (This is what was hanging me up at the end.)


Thanks pksiv and dslevine. Much appreciated!
graham.


Top
 Profile  
 
 Post subject: THANKS!! (and a question)
PostPosted: Fri Feb 24, 2006 1:27 pm 
Beginner
Beginner

Joined: Fri Feb 24, 2006 1:18 pm
Posts: 25
Caulfield:

THANK YOU! I had the same problem and your solution worked perfectly for me (and was incredibly clear and well written).

Now, my question is whether anyone knows why this isn't documented? The online documentation (for 2.x, which is the version I am using right now) says in 6.6:
Quote:
You must specify a comparator in the mapping file:
....
<map name="holidays" sort="my.custom.HolidayComparator" lazy="true">


Yesterday, my copy of Hibernate in Action arrived and on page 215 it has an example similar to the above.

Perhaps I am not smart enough, but from the above documentation I would have never arrived at the solution. Your post (and the help of the others in this thread) saved the day. But, IMHO, it seems too much of a leap from what is documented to what is required. Thus, my question is:
* Are we missing something simpler?
* Is the "leap" obvious to more experienced Java developers?
* Are custom comparators extremely rare, so this area just hasn't been well documented?

Just wondering...

Thanks again!
RB


Top
 Profile  
 
 Post subject: Inner classes
PostPosted: Fri Feb 24, 2006 1:50 pm 
Newbie

Joined: Fri Sep 26, 2003 11:44 am
Posts: 13
Hi,

The hibernate documentation is sensible. The naming convention for inner classes is standard. Static inner classes are really the only inner classes that Hibernate will able to instantiate. Non-static inner classes have to be instantiated from an object, e.g.

A.B foo = a.new B();

Since Hibernate doesn't have an object to instantiate it cannot do this. Logically a comparator as an inner class in the class it is comparing, should not be a non-static class as it shouldn't need data from a particular object instance.

Regards,

Ali

_________________
Ali Ibrahim


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

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.