Reputation: 7551
Here we have a Manifest class that includes list of students and teachers, both could be null.
class Manifest{
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "MANIFEST_STUDENT")
List<String> students = new ArrayList<String>();
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "MANIFEST_TEACHER")
List<String> teachers = new ArrayList<String>();;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(name = "MANIFEST_OTHERS")
List<String> others = new ArrayList<String>();;
}
on the UI, there are two multiple select
, one for student
and one for teacher
that let user choose for current manifest.
here is the problem:
When user deselect
all students
or teachers
from the list(meaning remove all students or teachers from current manifest
) and click save, unfortunately nothing can be saved, from UI and database it shows that the multiselect
chosen looks the SAME
as before.
from service layer, the code is simply like this.
manifest.merge();
It seems we must keep at least one
student or teacher for the collection field to make the change valid. So what's going on here and what is the solution? BTW, we are on Openjpa.
Upvotes: 0
Views: 1178
Reputation: 8463
Initializing a value in a JPA managed class, such as class Manifest
, has no bearing on what, or how, JPA will create the class as JPA maps extracted rows to the class. In particular, the result of:
List<String> students = new ArrayList<String>();
is likely to be:
ArrayList<String>()
to students
.students
with the data it extracts - the empty ArrayList
is dereferenced/lost.If your code is clearing a list, such as students
, use obj.getStudents().clear()
. More likely to run into problems if you call obj.setStudents(someEmptyList)
.
The issue here is how the JPA manager handles empty datasets: as null
or as an empty list. The JPA spec (old, not sure about the just released update) doesn't take a position on this point. A relevant article here.
From your comments, it's apparent that OpenJPA may not be respecting a null
value for a Collection
/List
, while it happily manages the necessary changes for when the value is set to an empty list instead. Someone knowing more about OpenJPA than I may be able to help at this stage - meanwhile you've got a workaround.
Upvotes: 0
Reputation: 7551
Kind of resolve the issue, more like a work around:
Before calling merge()
, place several condition checkers to make sure the collection fields are not null
public void save(Manifest entity) {
if(entity.getStudents()==null){
entity.setStudents(new ArrayList<String>());
}
if(entity.getTeachers()==null){
entity.setTeachers(new ArrayList<String>());
}
if(entity.getOthers()==null){
entity.setOthers(new ArrayList<String>());
}
entity.merge();
}
Simple as it, it seems the UI returns those collection fields as null even we initiate them as with empty String lists.
cheers.
Upvotes: 1