我遇到以下问题。
我有一个如下所示的实体:
@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():
从教师 t 中选择 t
- findTeacherByIdWithDetails(Long id):
从教师 t 中选择 t JOIN FETCH t.students,其中 t.id = :id
只要我在服务器端,一切都很好。
我在 Wildfly 10 应用程序服务器上使用 Hibernate。
我有 2 个 SOAP Web 服务方法,一种用于返回所有教师的方法,另一种用于通过加载学生的 ID 返回一位教师的方法。
现在,当我调用 webservice 方法返回所有教师时,当然会抛出 LazyInitializationException,因为教师实体已经分离。
现在这是我的问题。除了为此实体创建 DTO 之外还有其他选择吗?
如果我为学生集合设置 @XMLTransient
,那么当我为详细的教师调用 Web 服务方法时,我也会隐藏它。
如果你能帮我解决这个问题,那就太好了...我尝试了很多,我知道它可以通过使用 jackson-datatype-hibernate 与 REST 一起使用。但它必须是 SOAP Web 服务。
最佳答案
您可以尝试使用自定义 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<>();
关于java - 通过 SOAP 传输的 JPA 延迟加载集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47347131/