I have an Entity (RiskModel) that contains a Set of Embeddables (DiscreteTerms). Everything loads fine, but when I try to remove elements from the Set, Hibernate issues individual DELETE statements which fail to match anything because DiscreteTerm contains a floating-point field (coefficient). The WHERE clause doesn't actually match, I think due to floating-point precision issues.
I can think of two ways to solve this:
- Have Hibernate delete the whole collection and re-create it upon every modification. (This would be OK because this operation is rare.)
- Have Hibernate not include the coefficient in the WHERE clause. (This would be OK because the Set should not contain elements that differ only by coefficient.)
But I'm not sure how to make Hibernate do either of the above. Can anybody provide guidance? Or come up with a different solution?
Here is the relevant code:
Code:
@Entity
public class RiskModel implements Comparable<RiskModel>
{
private Set<DiscreteTerm> fDiscreteTerms = new HashSet<>();
// ... snip ...
/**
* <p>The {@link DiscreteTerm}s in the model's sum. Mutable.</p>
*/
@ElementCollection(fetch = FetchType.EAGER) // eager-load due to close association
// Override strange defaults.
@CollectionTable(
name = "risk_model_discrete_term",
joinColumns = @JoinColumn(name = "risk_model_id"))
public Set<DiscreteTerm> getDiscreteTerms()
{
return fDiscreteTerms;
}
/**
* For reflection-based construction only. Business code should modify the
* Set returned by {@link #getDiscreteTerms()}.
*/
void setDiscreteTerms(Set<DiscreteTerm> disceteTerms)
{
fDiscreteTerms = disceteTerms;
}
// .. snip ...
Code:
@Embeddable
public final class DiscreteTerm extends SingleVariableTerm
{
private float fCoefficient = 0.0f;
private DiscreteVariable fVariable = null;
private int fOptionIndex = -1;
@Basic
public float getCoefficient()
{
return fCoefficient;
}
public void setCoefficient(float coefficient)
{
fCoefficient = coefficient;
}
@Override
@ManyToOne(optional = false, targetEntity = AbstractVariable.class)
public DiscreteVariable getVariable()
{
return fVariable;
}
/**
* For reflection-based construction only. The associated Variable should
* not be changed.
*/
void setVariable(final DiscreteVariable variable)
{
fVariable = Objects.requireNonNull(variable);
}
@Basic
public int getOptionIndex()
{
return fOptionIndex;
}
/**
* For reflection-based construction only. The associated option should not
* be changed.
*/
void setOptionIndex(final int optionIndex)
{
fOptionIndex = optionIndex;
}
@Override
public boolean equals(final Object o)
{
// [snip], compares coefficient, variable, and optionIndex
}
@Override
public int hashCode()
{
return Objects.hash(getCoefficient(), getVariable(), getOptionIndex());
}
}