【问题标题】:JPA LazyLoading Collections transfered via SOAP通过 SOAP 传输的 JPA 延迟加载集合
【发布时间】:2017-11-17 09:22:05
【问题描述】:

我遇到了以下问题。
我有一个看起来像这样的实体:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Teacher{

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;      

  @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
  @JoinColumn(name = "teacherId", referencedColumnName = "id", nullable = false)
  private final Set<Student> students = new HashSet<>();
}

现在我有两种查找方法:

  • findAllTeachers(): SELECT t from Teacher t
  • findTeacherByIdWithDetails(长 ID):SELECT t from Teacher t JOIN FETCH t.students s where t.id = :id

只要我在服务器端,一切都很好。 我在 Wildfly 10 应用服务器上使用 Hibernate。

我有 2 种 SOAP 网络服务方法,一种用于返回所有教师的方法,另一种用于在加载学生的情况下按 id 返回一位教师的方法。

现在,当我调用 web 服务方法返回所有教师时,当然会抛出 LazyInitializationException,因为教师实体已经分离。

现在这是我的问题。除了为此实体创建 DTO 之外,还有其他选择吗? 如果我为学生集合设置@XMLTransient,当我为详细的教师调用webservice方法时,我也会隐藏它。

如果你能帮我解决这个问题,那就太好了……我尝试了很多,我知道它可以通过使用 jackson-datatype-hibernate 与 REST 一起工作。但它必须是 SOAP 网络服务。

【问题讨论】:

    标签: java hibernate soap lazy-loading


    【解决方案1】:

    您可以尝试使用自定义 XmlAdapter 来处理未初始化的 Hibernate 集合,例如:

    public class StudentSetXmlAdapter extends XmlAdapter<Set<Student>, Set<Student>> {
    
        @Override
        public Set<Student> marshal(Set<Student> value) throws Exception {
            //PersistentSet is the Hibernate's implementation of Set that handle Lazy-loading etc...
            if (value instanceof PersistentSet) {
                PersistentSet hibernateCollection = (PersistentSet) value;
    
                //If the data were already loaded you return the collection 
                return hibernateCollection.wasInitialized() ? value : null;
            } else
                return value;
        }
    
        @Override
        public Set<Student> unmarshal(Set value) throws Exception {
            return value;
        }
    
    }
    

    并在您的字段上添加注释@XmlJavaTyAdapter

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "teacherId", referencedColumnName = "id", nullable = false)
    @XmlJavaTypeAdapter(StudentSetXmlAdapter.class)
    private final Set<Student> students = new HashSet<>();
    

    【讨论】:

    • 感谢您的回答 Baptiste Beauvais,不幸的是,现在我得到了异常:java.util.Set 是一个接口,JAXB 无法处理接口:-/ 所以我尝试使用包装类,但我' m 无法生成看起来像 Sets 的标准输出的输出...
    猜你喜欢
    • 2016-12-21
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    相关资源
    最近更新 更多