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