Q:

Should my equals/hashCode method examine more than the object IDs?

In my application, I have model classes of the following form:
class Book
{
    private int ID;
    private String title;

    //other code
}

Now my question is two part:

Is the following a good implementation of the equals() method?
public boolean equals(Object o)
{
    if(o == null)
    {
        return false;
    }

    if(!(o instanceof Book))
    {
        return false;
    }

    Book other = (Book)o;

    if(o.getID() == ID)
    {
        return true;
    }
    return false;
}

I know that equals() implementation largely depends on my
application business logic. But If two Books have the same ID then
they ideally must be the same Book. Hence I am confused as to
whether I should check for equality for other value fields as well
[title, price etc].
Is this a good implementation of the hashCode() method:
public int hashCode()
{
    return ID;
}

My thinking is that different books will have different IDs and if
two books have the same ID they they are equal. Hence the above
implementation will ensure a good distribution of the hashcode in
context of my application.

A:

Just wanted to add some coment over the previous answers. The contract of equals mentions that it must be symmetric. This means that a.equals(b) iff b.equals(a).
That's the reason why instanceof is usually not used in equals (unless the class is final). Indeed, if some subclass of Book (ComicsBook for example) overrides equals to test that the other object is also an instance of ComicsBook, you'll be in a situation where a Book instance is equal to a ComicsBook instance, but a ComicsBook instance is not equal to a Book instance. 
You should thus (except when the class is final or in some other rare cases) rather compare the classes of the two objects:
if (this.getClass() != o.getClass()) {
    return false;
}

BTW, that's what Eclipse does when it generates hashCode and equals methods.

A:

Don't do this:
if(o.getID() == ID)

ID is an Integer object, not a primitive.  Comparing two different but equal Integer objects using == will return false.
Use this:
if(o.getID().equals(ID))

You'd also need to check for ID being null.
Other than that, your logic is fine - you're sticking with the contract that says two equal objects must have the same hashcode, and you've made the business logic decision as to what equality means -a decision that only you can make (there's no one correct answer).

A:

If you use Hibernate then you have to consider some Hibernate related concerns.
Hibernate create Proxies for Lazy Loading.

always use getter to access the properties of the other object (you already done that)
even if it is correct to use if (!this.getClass().equals(o.getClass())) { return false;} in a normal Application it WILL fail for hibernate Proxy (and all other proxies). The reason is if one of the two is a proxy, there classes will never be equals. So the test if(!(o instanceof Book)){return false;} is what you need.

If you want to do it in the symmetric way than have a look at org.hibernate.proxy.HibernateProxyHelper.getClassWithoutInitializingProxy() with help of this class you can implement:
if (!HibernateProxyHelper.getClassWithoutInitializingProxy(this)
     .equals(HibernateProxyHelper.getClassWithoutInitializingProxy(o))) {
   return false;
}

An other problem maybe is the ID -- when you assign the id not with the creation of an new object but later on while storing them, then you can run into trouble. Assume this scenario: You create a new Book with id 0, then put the Book in a HashSet (it will assigned to an bucket in the hashset depending on the hashcode), later on you store the Book in the Database and the id is set to lets say 1. But this changes the hashcode, and you will have problems to find the entity in the set again. -- If this is a problem or not for you, strongly depends on your application, architecture and how you use hibernate.

