Hi Jon,
Persistence context and the shared (2nd-level) cache manage objects by its
primary key value. And the objects in the shared cache are not returned but
the clones of them are actually returned. Persistence context also manages
objects with their referencial identity (using IdentityHashtable similar to
Java SE IdentityMap). These allow that the same object is returned for the
same primary key by em.find() or query in the same PC. equals() is not used
as it can be overrided by users.
I think there is no problem using many-to-one associated object in equals()
in your entity(lazy loading is not used for many-to-one by default).
Hope this helps,
-Wonseok
On 1/14/07, Jon Miller <jemiller_at_uchicago.edu> wrote:
>
> 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
>