persistence@glassfish.java.net

How does TopLink know if an object is in the cache?

From: Jon Miller <jemiller_at_uchicago.edu>
Date: Sat, 13 Jan 2007 14:04:34 -0600

Hi all,

I'm wondering how TopLink determines whether an object is in the cache? I'm
guessing that it uses reference equality. Or does it use object equality?
i.e. does it do a,

if(o == o2) ...

or a,

if(o.equals(o2)) ...

I'm wondering if some of the issues that I've been running into may have to
do with me incorrectly implementing Object.equals().

The other thing that I'm wondering about is if it's OK to refer to objects
that are annotated with @ManyToOne in the equals comparison. For example, I
have the following class. A schedule is uniquely identified by it's location
and startTime. I'm wondering referring to the location in the equals
comparison might cause problems with regard to lazy loading or otherwise?

package edu.uchicago.at.schedules.persistence.entity;

import edu.uchicago.at.common.persistence.entity.AuditObject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name="Schedule")
public class Schedule extends AuditObject implements Comparable<Schedule> {
    private Integer id;
    private Location location;
    private static Logger logger =
Logger.getLogger(Schedule.class.getName());
    private List<Shift> shifts = new ArrayList<Shift>();
    private Date startTime;

    public Schedule() {
    }

    public Schedule(Location location, Date startTime) {
        setLocation(location);
        setStartTime(startTime);
    }

    public int compareTo(Schedule schedule) {
        if(startTime == null && schedule.getStartTime() == null) {
            return 0;
        }
        if(startTime == null) {
            return -1;
        }
        if(schedule.getStartTime() == null) {
            return 1;
        }
        return startTime.compareTo(schedule.getStartTime());
    }

    public boolean equals(Object o) {
        if(this == o) {
            return true;
        }
        if(!(o instanceof Schedule)) {
            return false;
        }
        Schedule s = (Schedule)o;
        if(location == null && s.getLocation() != null
                || location != null && s.getLocation() == null) {
            return false;
        }
        if(location != s.getLocation() && !location.equals(s.getLocation()))
{
            return false;
        }
        if(startTime == null && s.getStartTime() != null
                || startTime != null && s.getStartTime() == null) {
            return false;
        }
        if(startTime != s.getStartTime()
                && startTime.getTime() != s.getStartTime().getTime()) {
            return false;
        }
        return true;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="Id")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @ManyToOne @JoinColumn(name="LocationId", nullable=false)
    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    @OneToMany(mappedBy="schedule", cascade=CascadeType.ALL)
    @OrderBy("startTime")
    public List<Shift> getShifts() {
        return shifts;
    }

    public void setShifts(List<Shift> shifts) {
        this.shifts = shifts;
    }

    @Column(name="StartTime", nullable=false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public int hashCode() {
        int i = 17;
        if(location != null) {
            i = 37 * i + location.hashCode();
        }
        if(startTime != null) {
            i = 37 * i + startTime.hashCode();
        }
        return i;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append(String.format("id = %d", id));
        sb.append(String.format(", location = %s", location));
        sb.append(String.format(", startTime = %s", startTime));
        sb.append(String.format(", shifts = %s", shifts));
        sb.append("]");
        return sb.toString();
    }
}

Jon