JPA returning null for deleted items from a set
This may be related to my question from a few days ago, but I'm not even sure how to explain this part. (It's an entirely different parent-child relationship.)
In my interface, I have a set of attributes (Attribute) and valid values (ValidValue) for each one in a one-to-many relationship. In the Spring MVC frontend, I have a page for an administrator to edit these values. Once it's submitted, if any of these fields (as <input> tags) are blank, I remove the ValidValue object like so:
Set<ValidValue> existingValues = new HashSet<ValidValue>(attribute.getValidValues());
Set<ValidValue> finalValues = new HashSet<ValidValue>();
for(ValidValue validValue : attribute.getValidValues()) {
if(!validValue.getValue().isEmpty()) {
finalValues.add(validValue);
}
}
existingValues.removeAll(finalValues);
for(ValidValue removedValue : existingValues) {
getApplicationDataService().removeValidValue(removedValue);
}
attribute.setValidValues(finalValues);
getApplicationDataService().modifyAttribute(attribute);
The problem is that while the database is updated appropriately, the next time I query for the Attribute objects, they're returned with an extra entry in their ValidValue set -- a null, and thus, the next time I iterate through the values to display, it shows an extra blank value in the middle. I've confirmed that this happens at the point of a merge or find, at the point of "Execute query ReadObjectQuery(entity.Attrib开发者_Go百科ute).
Here's the code I'm using to modify the database (in the ApplicationDataService):
public void modifyAttribute(Attribute attribute) {
getJpaTemplate().merge(attribute);
}
public void removeValidValue(ValidValue removedValue) {
ValidValue merged = getJpaTemplate().merge(removedValue);
getJpaTemplate().remove(merged);
}
Here are the relevant parts of the entity classes:
Entity
@Table(name = "attribute")
public class Attribute {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "attribute")
private Set<ValidValue> validValues = new HashSet<ValidValue>(0);
}
@Entity
@Table(name = "valid_value")
public class ValidValue {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "attr_id", nullable = false)
private Attribute attribute;
}
Another JPA issue fixed by hours of random experimentation. Hopefully this will help someone else with the same kind of issue.
The problem, apparently, was that I was trying to remove the modified object. Essentially, what I was doing was letting the Spring form modify the ValidValue objects directly, and then iterating through to throw out any that were modified to a value of "" (empty string).
Once that got to the data manager, I tried to remove in two steps:
- a) Merge, which sent an update to the object in the database, setting the value to "".
- b) Remove the merged object, which sent the delete.
In this sequence, the next time I got the Attribute object, for some reason, there was an extra null value in the set. If I got all ValidValue objects, no such issue.
I changed it to do the following instead:
- a) Get a new object through a find on the ID of the removed object.
- b) Remove that new object.
Lo and behold, that solved the issue! (I'd appreciate any comments about how what I did was entirely wrong and will lead to issues down the road, but for now, it works.)
精彩评论