JPA LazyLoading Collections通过SOAP传输

时间:2017-11-17 09:22:05

标签: java hibernate soap lazy-loading

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

@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(Long id):SELECT t from Teacher t JOIN FETCH t.students s where t.id = :id

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

我有两个SOAP webservice方法,一个返回所有教师的方法和一个方法,用于在学生加载的情况下通过id返回一个教师。

当然,当我调用webservice方法返回所有教师时,抛出了LazyInitializationException,因为教师实体已经分离。

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

如果你可以帮我解决这个问题,那将是非常好的...我尝试了很多,我知道它可以通过使用jackson-datatype-hibernate与REST一起工作。但它必须是SOAP Web服务。

1 个答案:

答案 0 :(得分:0)

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

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