Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[eclipselink-users] Caching and Relational Objects

Hello,

   I have the following domain objects (retained only the relevant information - or what I thought to be relevant)

@Entity
@Table(name = "RSRCHOUR")
public class ResourceHour
  implements Serializable {
    private Integer m_hourId;
    private TimesheetPeriod m_timesheetPeriod;

    @TableGenerator(name = "rsrchour_rsrc_hr_id", table = "NEXTKEY", pkColumnValue = "rsrchour_rsrc_hr_id", allocationSize = 1, pkColumnName = "KEY_NAME", valueColumnName = "KEY_SEQ_NUM")
    @Id
    @GeneratedValue(strategy = TABLE, generator = "rsrchour_rsrc_hr_id")
    @Column(name = "RSRC_HR_ID")
    public Integer getHourId() {
        return m_hourId;
    }
    public void setHourId(Integer hourId){
        m_hourId = hourId;
    }

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="TS_ID", referencedColumnName="TS_ID")
    public TimesheetPeriod getTimesheetPeriod() {
        return m_timesheetPeriod;
    }
    public void setTimesheetPeriod(TimesheetPeriod timesheetPeriod) {
        m_timesheetPeriod = timesheetPeriod;
    }
}

@Entity
@Table(name = "TSDATES")
public class TimesheetPeriod
  implements Serializable {
    private Integer m_timesheetPeriodId;
    private Date m_startDate;
    private Date m_endDate;

    @TableGenerator(name = "timesht_ts_id", table = "NEXTKEY", pkColumnValue = "timesht_ts_id", allocationSize = 1, pkColumnName = "KEY_NAME", valueColumnName = "KEY_SEQ_NUM")
    @Id
    @Column(name = "TS_ID", nullable = false, length = 10)
    public Integer getTimesheetPeriodId() {
        return m_timesheetPeriodId;
    }
    public void setTimesheetPeriodId(Integer timesheetPeriodId) {
        m_timesheetPeriodId = timesheetPeriodId;
    }

    @Temporal(TemporalType.DATE)
    @Column(name = "END_DATE", nullable = false)
    public Date getEndDate(){
        return m_endDate;
    }
    public void setEndDate(Date endDate){
        m_endDate = endDate;
    }

    @Temporal(TemporalType.DATE)
    @Column(name = "START_DATE", nullable = false)
    public Date getStartDate(){
        return m_startDate;
    }
    public void setStartDate(Date startDate){
        m_startDate = startDate;
    }

    @Override
    public int hashCode() {
        return (m_timesheetPeriodId == null) ? 0 : m_timesheetPeriodId.intValue();
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final TimesheetPeriod other = (TimesheetPeriod)obj;
        if (m_timesheetPeriodId == null) {
            if (other.m_timesheetPeriodId != null) {
                return false;
            }
        }
        else if (!m_timesheetPeriodId.equals(other.m_timesheetPeriodId)) {
            return false;
        }
        return true;
    }
}

// I exercise these domain objects as follows
TimesheetPeriod tp = new TimesheetPeriod();
tp.setTimesheetPeriodId(Integer.valueOf(timesheetTask.getTsId())); // only setting the key field, ignoring other fields
ResourceHour hour = new ResourceHour();
hour.setTimesheetPeriod(tp);
m_hoursDao.save(hour);  // JPA call to save the domain object

// assuming an initial cache state of empty, I end up with the following cache state
UnitOfWorkIdentityMap for: TimesheetPeriod
Key: [10]    Identity Hash Code: 20015579    Object: TimesheetPeriod[TimesheetPeriodId: 10 StartDate: null EndDate: null

I then load the TimesheetPeriod using a Query, the timesheet period returned is the one from cache. I noticed that a "database query is issued" to load the actual database row and prior to using ObjectBuilder a check is made in the cache to retreive an existing object if available in the cache.

From the database schema I know that both startdate and enddate fields cannot be null. I therefore use them field values without a check which results in a NPE.

I can think of only 1 fix which is to load the TimesheetPeriod rather than creating one in memory and setting the primary key as I have at this time.

Questions:
* What is the expected/accepted usage pattern with regards to cache, is the use case of creating objects in memory with only primary key fields invalid/incorrect?
* When using a query to load from the database eclipselink always issues a query and only uses the results (AbstractRow instances) to use primary key references to retrieve objects from cache, avoidinh new object creation, am I doing something wrong or can I get eclipselink to make proper use of the cache avoiding network round trips (database queries) when loading using queries?
* What is the correct implementation for hashcode and equals for domain objects, should they just be off primary key fields or all fields, will using all fields help with my caching issue, I am guessing not as eclipse link seems to use primary key field equals (via ClassDescriptor instances) and not the hashcode/equals combination for its cache.

Any other fixes are welcome

Thanks
Bhaskar

Back to the top