-->
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.  [ 2 posts ] 
Author Message
 Post subject: Composite Key Updated with NULL after insert
PostPosted: Tue May 22, 2007 5:30 pm 
Newbie

Joined: Wed Jan 31, 2007 7:27 pm
Posts: 3
I'm having a problem mapping a legacy database which has a composite key, that contains a foreign key to it's parent.

There are two objects, Project (parent) and FinancialCost (child). Project contains a collection (bag mapped to a list) of FinancialCosts. FinancialCost has a composite key of the proejctId (the parent) and an integer, fiscalYear. The mappings are below. A adding costs to a project that did not previously have costs, hHibernate inserts each FinancialCost individually (expected), then call updates the parent Project (also expected). The but then it calls the following SQL:

Code:
update
        CCRTRK_PROJ_FIN_CST
    set
        PROJ_ID=null
    where
        PROJ_ID=?


...aparently attempting to set the projectId (part of the composite key) back to NULL. I have no idea why it would attempt to do this or how to stop it. Everything appears fine, up until that update. Any help would be appreciated.

Thanks,

Jon DeJong

Mappings:

Code:
<hibernate-mapping package="com.....model">
    <class name="Project" table="CCRTRK_PROJ" lazy="false" dynamic-update="true">
        <id name="id" type="long">
            <column name="PROJ_ID" />
            <generator class="sequence">
               <param name="sequence">ccrtrk_proj_seq</param>
            </generator>
        </id>

...

<bag name="costs"
            inverse="false"
            cascade="all"
            order-by="PROJ_FIN_CST_YR_NBR"
            lazy="false">
           <key column="PROJ_ID"/>
           <one-to-many class="FinancialCost"/>
       </bag>

...

</class>
</hibernate-mapping>

hibernate-mapping package="com.....model">
    <class name="FinancialCost" table="CCRTRK_PROJ_FIN_CST" lazy="false">
       
        <composite-id name="costId" class="FinancialCostId">
           <key-property name="projectId" type="long" column="PROJ_ID" />
           <key-property name="fiscalYear" type="int" column="PROJ_FIN_CST_YR_NBR"/>
      </composite-id>

....

</hibernate-mapping>




Project Class (Entity is a class that simply contains a Long id member with getter and setter):


Code:

public class Project extends Entity {
...
private List<FinancialCost> costs;

   public List<FinancialCost> getCosts() {
      return costs;
   }

   public void setCosts(List<FinancialCost> costs) {
      this.costs = costs;
   }
...
}


FinancialCost class:

Code:

public class FinancialCost implements Serializable{
   private static final long serialVersionUID = 1L;

...

private FinancialCostId costId;

public FinancialCostId getCostId() {
      return costId;
   }
   public void setCostId(FinancialCostId costId) {
      this.costId = costId;
   }

...

}



FinancialCostId class:

Code:
public class FinancialCostId implements Serializable {
   private static final long serialVersionUID = 1L;
   private Long projectId;
   private Integer fiscalYear;
   
   public FinancialCostId(){
      
   }
   
   public FinancialCostId(Long id, Integer fiscalYear){
      this.projectId = id;
      this.fiscalYear = fiscalYear;
   }

   public Integer getFiscalYear() {
      return fiscalYear;
   }

   public void setFiscalYear(Integer fiscalYear) {
      this.fiscalYear = fiscalYear;
   }

   public Long getProjectId() {
      return projectId;
   }

   public void setProjectId(Long id) {
      this.projectId = id;
   }

   @Override
   public int hashCode() {
      final int PRIME = 31;
      int result = super.hashCode();
      result = PRIME * result + ((fiscalYear == null) ? 0 : fiscalYear.hashCode());
      result = PRIME * result + ((projectId == null) ? 0 : projectId.hashCode());
      return result;
   }

   @Override
   public boolean equals(Object obj) {
      if (this == obj)
         return true;
      if (!super.equals(obj))
         return false;
      if (getClass() != obj.getClass())
         return false;
      final FinancialCostId other = (FinancialCostId) obj;
      if (fiscalYear == null) {
         if (other.fiscalYear != null)
            return false;
      } else if (!fiscalYear.equals(other.fiscalYear))
         return false;
      if (projectId == null) {
         if (other.projectId != null)
            return false;
      } else if (!projectId.equals(other.projectId))
         return false;
      return true;
   }
}



New FinancialCosts are attached to a Project here:

Code:

public void createFinancials(){
      Project project = getProject();
      List<FinancialCost> costs = new ArrayList<FinancialCost>();
      
      for(int year = getFirstYear(); year<=getLastYear; year++){
         FinancialCost financialCost = new FinancialCost();
         financialCost.setCostId(new FinancialCostId(project.getId(), year));
         costs.add(financialCost);
      }
      project.setCosts(costs);
   }



Project object is updated using Spring's HibernateTemplate:

Code:

public void update(Project project) {
... some business rules are here ...
      hibernateTemplate.saveOrUpdate(project);
   }



Again, any help would be appreciated!

Thanks,
Jon


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 22, 2007 10:26 pm 
Newbie

Joined: Wed Jan 31, 2007 7:27 pm
Posts: 3
I solved it. In case anyone else experience a similar issue, here's the solution:

Inside of Hibernate, where it processes saveOrUpdate(), it processes each property of the entity (makes sense). When processing a collection, it checks to see if the collection is of type PersistentCollection. If it is not, it adds it to the list of collections to be removed. In my circumstance, this caused the seemingly odd result described above. The workaround in my code is done by modifying this method:

Code:
public void createFinancials(){
      Project project = getProject();
      List<FinancialCost> costs = new ArrayList<FinancialCost>();
     
      for(int year = getFirstYear(); year<=getLastYear; year++){
         FinancialCost financialCost = new FinancialCost();
         financialCost.setCostId(new FinancialCostId(project.getId(), year));
         costs.add(financialCost);
      }
      project.setCosts(costs);
   }


project.costs is already of type PersistantBag, just an empty PersistantBag. Changing it to an ArrayList causes Hibernate to add it to the remove list. This version of the method works:

Code:
public void createFinancials(){
      Project project = getProject();
      List<FinancialCost> costs = project.getCosts();
     
      for(int year = getFirstYear(); year<=getLastYear; year++){
         FinancialCost financialCost = new FinancialCost();
         financialCost.setCostId(new FinancialCostId(project.getId(), year));
         costs.add(financialCost);
      }
      project.setCosts(costs);
   }


Cheers!
Jon


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.