这里我们有一个Manifest类,其中包括学生和教师列表,两者都可以为空。
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>();;
}
在用户界面上,有两个multiple select
,一个用于student
,另一个用于teacher
,用户可以选择当前的清单。
问题在于:
当用户deselect
列出所有students
或teachers
时(意味着从当前manifest
删除所有学生或教师)并点击保存,很遗憾没有任何内容可以保存,从用户界面和数据库中可以看出,所选的multiselect
与之前的SAME
相同。
从服务层,代码就像这样。
manifest.merge();
似乎我们必须让at least one
学生或老师加入收集字段,以使更改生效。那么这里发生了什么,解决方案是什么?顺便说一下,我们在Openjpa上。
答案 0 :(得分:1)
有点解决问题,更像是解决问题:
在调用merge()
之前,请放置几个条件检查器以确保收集字段不为空
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();
}
简单,似乎UI将这些集合字段返回为null,即使我们使用空字符串列表启动它们。
欢呼声。
答案 1 :(得分:0)
初始化JPA托管类中的值(例如class Manifest
)与JPA将创建类的内容或方式无关,因为JPA将提取的行映射到类。特别是,结果:
List<String> students = new ArrayList<String>();
很可能是:
ArrayList<String>()
分配给students
。students
- 空ArrayList
被解除引用/丢失。如果您的代码正在清除列表,例如students
,请使用obj.getStudents().clear()
。如果拨打obj.setStudents(someEmptyList)
,则更有可能遇到问题。
此处的问题是JPA管理器如何处理空数据集:null
或空列表。 JPA规范(旧的,不确定刚刚发布的更新)在这一点上没有采取立场。一个relevant article here。
根据您的评论,很明显OpenJPA可能不尊重null
/ Collection
的{{1}}值,而它很乐意管理值设置为何时所需的更改而是一个空列表。有人对OpenJPA了解得比我在这个阶段可能提供的帮助更多 - 同时你有一个解决方法。