当此字段是集合时,JPA MERGE无法更新实体字段值(使用ElementCollection)

时间:2013-06-24 16:05:49

标签: spring java-ee jpa ejb

这里我们有一个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列出所有studentsteachers时(意味着从当前manifest删除所有学生或教师)并点击保存,很遗憾没有任何内容可以保存,从用户界面和数据库中可以看出,所选的multiselect与之前的SAME相同。

从服务层,代码就像这样。

manifest.merge();

似乎我们必须让at least one学生或老师加入收集字段,以使更改生效。那么这里发生了什么,解决方案是什么?顺便说一下,我们在Openjpa上。

2 个答案:

答案 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>();

很可能是:

  • 在创建(通过JPA)新实例时,将ArrayList<String>()分配给students
  • JPA用它提取的数据覆盖students - 空ArrayList被解除引用/丢失。

如果您的代码正在清除列表,例如students,请使用obj.getStudents().clear()。如果拨打obj.setStudents(someEmptyList),则更有可能遇到问题。

此处的问题是JPA管理器如何处理空数据集:null空列表。 JPA规范(旧的,不确定刚刚发布的更新)在这一点上没有采取立场。一个relevant article here

根据您的评论,很明显OpenJPA可能不尊重null / Collection的{​​{1}}值,而它很乐意管理值设置为何时所需的更改而是一个空列表。有人对OpenJPA了解得比我在这个阶段可能提供的帮助更多 - 同时你有一个解决方法。