These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: How to model status and status history of an entity
PostPosted: Mon Mar 23, 2009 9:58 pm 
Newbie

Joined: Wed Nov 08, 2006 2:30 pm
Posts: 6
Hello,

I have a Person and the Person has a current status. The status can change, but I want to keep track of the status. That means that the person entity has two links two the status table. A one-to-one for the current status and one-to-many for the status history.

Code:
CREATE TABLE "Person" (
   "ID" NUMBER(19,0) NOT NULL,
   "NAME" VARCHAR2(256) NOT NULL,
   CONSTRAINT "PERSON_PK"  PRIMARY KEY ("ID")
);


CREATE TABLE "Status" (
   "ID" NUMBER(19,0) NOT NULL,
   "NAME" VARCHAR2(256) NOT NULL,
   "STATUS_DATE" TIMESTAMP NOT NULL,
   "PERSON_ID" NUMBER(19,0) NOT NULL,   
   CONSTRAINT "PERSON_PK"  PRIMARY KEY ("ID"),
   CONSTRAINT "STATUS_PERSON_FK" FOREIGN KEY  ("PERSON_ID") REFERENCES "PERSON" ("ID")
);


Here are the mappings as I have them right now:

Code:
@Entity(name = "PERSON")
public class Person {

  private Set<Status> statusHistory;
  private Status currentStatus;

    @OneToMany(mappedBy = "person", fetch = FetchType.LAZY)
    public List<Status> getStatusHistory() {
        return statusHistory;
    }
    public void setStatusHistory(List<Status> statusHistory) {
        this.statusHistory = statusHistory;
    }

    @OneToOne(mappedBy = "person",cascade = CascadeType.ALL)
    @Where(clause = "CREATE_DATE = (SELECT MAX(s.CREATE_DATE) FROM STATUS s WHERE s.PERSON_ID = PERSON_ID)")
    public Status getCurrentStatus() {
        return this.currentStage;   
    }
    public void setCurrentStatus(Status status) {
        this.currentStatus = status;
    }
}

@Entity(name="STATUS")
public class Status {
     private Person person;

    @ManyToOne()
    @JoinColumn(name = "PERSON_ID")
    public Person getPerson() {
           return this.person;
    }
    public void setPerson(Person person) {
        this.person = person;
    }
}



This model breaks on the one-to-one from Person to Status. It tells me that there are multiple rows in the result set. Looking at the SQL output I also see that the Where clause is ignored.

Do you have any suggestions on how to solve this problem in a good way? The person table could be rather big (over a million) and the status table could be much bigger. Therefore I am looking for a solution that would perform will with bigger datasets.

Thanks,
Johannes


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 24, 2009 2:48 pm 
Newbie

Joined: Wed Nov 08, 2006 2:30 pm
Posts: 6
I am sure that this is a rather common problem.

I also wanted to mention that there would be one easy around the problem:
I could delete the one-to-one mapping. In order to get then the most recent status I could use a filter on the status history collection. But that requires me to always load the whole collection. I don't think that this will perform well enough. So are there any other ways using what I described in my first posting?

Thank you


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 30, 2009 12:47 pm 
Newbie

Joined: Wed Nov 08, 2006 2:30 pm
Posts: 6
Isn't there anybody out there who had a similar problem?

So far I am using the method where I don't map the one-to-one for the current status, but I have a helper method to return the most recent item from the status-history collection. This is pretty inefficient, because I need to load the whole collection all the time.

If anybody has a better suggestions, please let me know.

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 30, 2009 9:49 pm 
Newbie

Joined: Wed Feb 23, 2005 9:57 pm
Posts: 16
What if you were to rename your status table and make it status_history. Whenever a person's status changes you make an entry in the status_history table.

If a person must always have a status, then add a current_status column to the person table and have it point to the status_history table;

Code:
CONSTRAINT "whatever" FOREIGN KEY  ("CURRENT_STATUS") REFERENCES "STATUS" ("ID")


Seems a bit weird though because the status_history also has the person_id so there's some circularity.

Alternatively (to the current_status column in the person table), make a current_status table and it has 2 columns, person_id and status_id, both foreign keys to the respective tables (person and status_history). So whenever a person's status changes, you add an entry to the status_history table, and update the current_status table to point to that entry.

I'm no database wizard, this is just off the top of my head.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.