persistence@glassfish.java.net

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

From: Jon Miller <jemiller_at_uchicago.edu>
Date: Tue, 16 Jan 2007 15:37:14 -0600

Thanks, that helps. Especially the part about IdentityMap. Also, the part
about it cloning the objects.

Jon

----- Original Message -----
From: "Wonseok Kim" <guruwons_at_gmail.com>
To: <persistence_at_glassfish.dev.java.net>
Sent: Tuesday, January 16, 2007 9:52 AM
Subject: Re: How does TopLink know if an object is in the cache?


> 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
>>
>