I could suggest the following way for generating serialVersionUID for java entities.
It is staible in sense that it depends only on your schema, not JVM/time or date of creation.
On other hand it depends on all fields in entity.
If we have next n fields:
typeName_1 fieldName_1;
typeName_2 fieldName_2;
...
typeName_n fieldName_n;
we could calculate
serialVersionUID =
(fieldName_1.hashCode() XOR typeName_1.hashCode()) * 31^0+
(fieldName_2.hashCode() XOR typeName_2.hashCode()) * 31^1 + ... +
(fieldName_n.hashCode() XOR typeName_n.hashCode()) * 31^n
where fieldName_i.hashCode() is hashCode() of fieldName_i string
(for int id; it will be "id".hashCode())
and typeName_i.hashCode() is hashCode() of typeName_i string
(for int id; it will be "int".hashCode())
so, we will be independent from
1) JVM
2) time/date of creation
and depend on
1) fields order
2) field types
3) field names
Tuesday, February 13, 2007
How to override equals() and hashCode() of persistent objects using ids
The problem described in details in http://www.hibernate.org/109.html
The problem is that if we implement equals()/hashCode() as comparison and hashCode() of entity's ids (see http://djeang.blogspot.com/2005/08/override-equals-and-hashcode-methods.html) then the hashCode() (and, possibly, equals()) will change after saving entities if ids are generated by DB.
To solve this issue I can suggest to use inner classes with equals()/hashCode(). It will not affect Hibernate's internal collections taskflow, but will allow you to use ids in equals()/hashCode() after entities are persisted. On other hand hashCode() and equals() will not change in your persistent objects after your saved it.
I even could suggest yo add it to entities code generation in such tools as Hibernate Tools.
I would like to mention also that SomeEntityId object could be stored in transient field of an entity.
Comments are wellcome.
The problem is that if we implement equals()/hashCode() as comparison and hashCode() of entity's ids (see http://djeang.blogspot.com/2005/08/override-equals-and-hashcode-methods.html) then the hashCode() (and, possibly, equals()) will change after saving entities if ids are generated by DB.
To solve this issue I can suggest to use inner classes with equals()/hashCode(). It will not affect Hibernate's internal collections taskflow, but will allow you to use ids in equals()/hashCode() after entities are persisted. On other hand hashCode() and equals() will not change in your persistent objects after your saved it.
public class Test3 {
static class SomeEntity {
private Integer id;
private String data;
public SomeEntity() {
super();
}
public SomeEntity(Integer id, String data) {
super();
this.id = id;
this.data = data;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public class SomeEntityId {
private SomeEntity link = null;
public SomeEntityId(SomeEntity link) {
super();
this.link = link;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if ((obj == null) || (obj.getClass() != this.getClass()))
return false;
if (this.link.getClass() != ((SomeEntityId) obj).getLink().getClass())
return false;
Integer thisId = link.getId();
Integer otherId = ((SomeEntityId) obj).getLink().getId();
if ((thisId == null) || (otherId == null))
throw new RuntimeException("Id not defined!");
return thisId.equals(otherId);
}
@Override
public int hashCode() {
Integer thisId = link.getId();
if (thisId == null)
throw new RuntimeException("Id not defined!");
return thisId.hashCode();
}
public SomeEntity getLink() {
return link;
}
};
public SomeEntityId getDTO() {
return new SomeEntityId(this);
}
}
public static void main(String[] args) {
SomeEntity e0 = new SomeEntity(null, "no id");
SomeEntity e1 = new SomeEntity(1, "e1");
SomeEntity e2 = new SomeEntity(2, "e2");
SomeEntity e3 = new SomeEntity(3, "e3");
SomeEntity e33 = new SomeEntity(3, "e33");
SetaSet = new HashSet ();
// aSet.add(e0.getDTO());
aSet.add(e1.getDTO());
aSet.add(e2.getDTO());
aSet.add(e3.getDTO());
aSet.add(e33.getDTO());
System.out.println("set size: " + aSet.size());
System.out.println("set:");
for (SomeEntity.SomeEntityId seId : aSet) {
SomeEntity se = seId.getLink();
System.out.println("entity: " + se.getData());
}
}
}
I even could suggest yo add it to entities code generation in such tools as Hibernate Tools.
I would like to mention also that SomeEntityId object could be stored in transient field of an entity.
Comments are wellcome.
Monday, February 12, 2007
No way to access overridden methods of superclass of superclass in Java
Let us consider an example:
It produces expected output
The point is that there is no way to call test() method of TestClass1 class!
won't compile but
will produce java.lang.StackOverflowError.
Despite on we can access superclass members of any level by casting this to appropriate class (see The Java Language Specification at http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.11.2), polymorphism allows us to access immediate superclass only, not overridden methods of higher levels (see The Java Language Specification at http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.4.9).
public class Test2 {
static class TestClass1 {
int x = 1;
String test() {
return "1";
}
}
static class TestClass2 extends TestClass1 {
int x = 2;
String test() {
return "2";
}
}
static class TestClass3 extends TestClass2 {
int x = 3;
int testX() {
return ((TestClass1)this).x;
}
String test() {
return super.test();
}
}
public static void main(String[] args) {
TestClass3 obj = new TestClass3();
System.out.println(obj.testX());
System.out.println(obj.test());
}
}
It produces expected output
1
2
The point is that there is no way to call test() method of TestClass1 class!
super.super.test()
won't compile but
((TestClass1)this).test()
will produce java.lang.StackOverflowError.
Despite on we can access superclass members of any level by casting this to appropriate class (see The Java Language Specification at http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.11.2), polymorphism allows us to access immediate superclass only, not overridden methods of higher levels (see The Java Language Specification at http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.4.9).
Labels:
class,
java,
method,
override,
polymorphism,
super,
superclass
Break and continue statements will stop exception flow
As it is said in The Java Language Specification (http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.15):
"The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any
Let's look into next example:
will produce output:
So, be extremely careful with your breaks!
"The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any
try
statements within the break target whose try
blocks contain the break
statement, then any finally
clauses of those try
statements are executed, in order, innermost to outermost, before control is transferred to the break target. Abrupt completion of a finally
clause can disrupt the transfer of control initiated by a break
statement."Let's look into next example:
public class Test {
private static void test() throws Exception {
for (int i = 0; i < 3; i++) {
try {
throw new Exception("Exception text");
} finally {
System.out.println("Finally exception " + i);
continue;
}
}
System.out.println("Impossible");
}
public static void main(String[] args) throws Exception {
test();
System.out.println("Impossible 2");
}
}
will produce output:
Finally exception 0
Finally exception 1
Finally exception 2
Impossible
Impossible 2
So, be extremely careful with your breaks!
Labels:
break,
continue,
exception,
java,
java language specification
Subscribe to:
Posts (Atom)