thanks JayeshJ,
my Bar class doesn't use the id in its equals(), nor am i trying to create two Bars that are equals() and both included in the Set (the kingdom/phylum isn't really what i'm using -- obviously a great many animals would compare as equals() if using only kingdom/phylum) but you're correct in seeing that something *is* wrong w/ my compareTo()/equals(). for reference, Bar looks like:
Code:
private String name;
private int kingdom;
private int phylum;
...
public int compareTo(Object o) {
Bar that = (Bar) o;
int result = kingdom - that.getKingdom();
if (result != 0) return result;
return phylum- that.getPhylum();
}
public boolean equals(Object o) {
if (this == o) return true;
if (! (o instanceof Bar)) return false;
Bar that = (Bar) o;
return ( (kingdom == that.getKingdom()) && (phylum== that.getPhylum()) );
}
public int hashCode() {
return 17*kingdom + 37*phylum;
}
which is wrong-ish since the kingdom/phylum aren't immutable and are used in compareTo(), equals(), and hashCode(). I understand that this will mess up any Set containing Bars that change while in the Set and because of that, it is perhaps not very good code. The above methods should ideally be written against immutable fields only.
the sequence of events that generates the problems is:
- persist a foo with a collection of Bars
- rearrange the collection as so:
Code:
Collection<Bar> barcopy = new HashSet<Bar>();
for (Bar bar: foo.getBars()) {
if (bar.getPhylum() == 5) bar.setPhylum(2);
barcopy.add(bar);
}
foo.getBars().clear();
foo.getBars().addAll(barcopy);
- merge the foo with the session
- commit the changes.
again, this isn't the real code, just a simple test case. there's only one entry in the collection that starts out with a phylum=5 and none that start out w/ a phylum=2.
if, between the clear() and addAll(), i perform a merge/commit it works because the clear() will delete everything from the DB and duplicate keys are then impossible (i'm forcing DELETE before INSERT).
how does this differ from how your non-exception-raising code works?
to the community: what is the *right* way to do what i'm trying? since, in the real problem, the reordering will be done on the client side for a bunch of Bars, must i really go through *each* collection replacing all elemnets with a clear()/merge()/flush()/addAll()/merge()/flush() cycle? this will be more than problematic, not just in DB inefficiency, but because the client would then become responsible for managing the collection.
up till now, everything i've done w/ Hibernate *just works* and has made managing of relationships quite simple (once i started to get the hang of it). so, i'm *certain* this is a problem w/ the way i'm doing something -- the Hibernate folks have anticipated seemingly any reasonable need and reordering a collection seems a reasonable need.
thanks again,
-don.