我们目前正试图找出解决常见问题的最佳解决方案。 以下是上下文:
这就是我们项目的组成方式
model
个类,确保传递的数据有效。domain
个类,这些是带JPA注释的简单POJO。
当请求进入REST API时,会收到格式为model
对象的对象(作为JSON)。
然后将此对象转换为要保留的domain
对象。
最后,持久化对象将转换回model
对象以发送回视图。
当我们将model
对象转换为domain
对象时,我们必须处理子对象
但在某些情况下,model
对象没有加载子对象,然后我们遇到了一个LazyLoading异常。
model
班
public class Classroom {
private final String name;
private final RoomCapacity roomCapacity;
private final Set<RoomEquipment> equipments = new HashSet<>();
private Long id;
@JsonCreator
public Classroom(@JsonProperty("name") final String name, @JsonProperty("roomCapacity") final RoomCapacity roomCapacity) {
if (StringUtils.isBlank(name)) {
throw new IllegalArgumentException("Cannot build a " + getClass().getName() + " without a name.");
}
if (roomCapacity == null) {
throw new IllegalArgumentException("Cannot build a " + getClass().getName() + " without a " + RoomCapacity.class.getName());
}
this.name = name;
this.roomCapacity = roomCapacity;
}
}
domain
班
@Entity
@Table(name = "classroom")
public class ClassroomDomain implements ModelTransformable<Classroom, Long> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CLASSROOM_ID")
private Long id;
@Column(unique = true)
private String name;
@OneToMany(mappedBy = "primaryKey.classroom", cascade = CascadeType.REMOVE)
private Set<RoomEquipmentDomain> equipments = new HashSet<>();
private int capacity;
public ClassroomDomain(Classroom classroom) {
if (classroom == null) {
throw new IllegalArgumentException("Cannot instantiate a " + getClass().getName() + " with a null " + Classroom.class.getName());
}
id = classroom.getId();
name = classroom.getName();
capacity = classroom.getRoomCapacity().getMaxCapacity();
classroom.getEquipments().forEach(e -> equipments.add(new RoomEquipmentDomain(e, this)));
}
@Override
public Classroom toModel() {
Classroom classroom = new Classroom(name, new RoomCapacity(capacity));
classroom.setId(id);
equipments.forEach(e -> classroom.addEquipment(e.toModel()));
return classroom;
}
}
如您所见,domain
类有一个带有model
对象的构造函数。并且domain
可以转换为模型。
因此,当我需要将domain
转换为model
时,它失败了,因为在某些情况下,我没有加载equipments
列表,然后我遇到了一个LazyLoading异常。
当我在DAO中调用toModel()
时,它会崩溃。
public Classroom findOneById(Long id) {
if (id == null) {
throw new IllegalArgumentException("Cannot find a " + Classroom.class.getName() + " with a null id.");
}
ClassroomDomain domain = classroomRepository.findOne(id);
if (domain == null) {
throw new ClassroomNotFoundException("No " + Classroom.class.getName() + " found for id :" + id);
}
return domain.toModel();
}
model
类,因为此应用程序需要是多个程序的通用API,因此我们需要一个可靠的模型。EAGER
loading。
我们如何在不遇到异常的情况下将数据从domain
转换为model
,这种情况下的最佳做法是什么。
答案 0 :(得分:1)
我认为你可以使用Open Session in View (or Transaction in View)
设计模式,在用户请求结束之前保持数据库连接打开。
当应用程序访问一个惰性集合时,Hibernate / JPA会毫无问题地进行数据库查询,不会抛出任何异常。
希望这有帮助。
答案 1 :(得分:0)
我最终决定创建:
不是最好的解决方案,但我找不到另一个。
答案 2 :(得分:0)
有一个名为Blaze-Persistence Entity Views的库。您仍然需要两种方法,但是由于实体视图已应用于现有查询,因此必要时它们可以重用相同的查询逻辑。请注意,这也将提高性能,因为它只会获取您实际映射的数据。
我甚至有一个关于您的确切用例的示例,external model。通过从外部模型扩展并通过constructor mapping传递数据,可以保持外部模型独立,同时获得良好的性能,避免使用EAGER
。