java - HIbernate - 尝试获取数据时出现“无法初始化代理 - 无会话”错误
问题描述
我正在使用 Spring Boot 和 MySql 休眠,我正在尝试找出处理错误的最佳方法
nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: "some class field" could not initialize proxy - no Session".
我看到了几个解决方案,但我无法让它们发挥作用,而且我也不明白实施它们的影响。
我有以下实体:
@Entity
@Table(name="machine_groups_to_versions")
@Getter
@Setter
//@JsonIgnoreProperties(value= {"machineGroup", "version"})
public class MachineGroupToVersion {
@Id
@GeneratedValue(strategy= GenerationType.AUTO, generator = "machine_groups_to_versions_seq")
@SequenceGenerator(name = "machine_groups_to_versions_seq", allocationSize = 1)
@Column(name = "id")
private long id;
@ManyToOne
@JoinColumn(name = "machine_group_id", nullable = false)
private MachineGroup machineGroup;
@ManyToOne
@JoinColumn(name = "version_id", nullable = false)
private Version version;
@Column(name = "state")
private String state;
@Column(name = "tested_time")
private Date testedTime;
@Column(name = "creation_time")
private Date creationTime;
}
@Entity
@Table(name="versions")
@Getter
@Setter
public class Version {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "versions_seq")
@SequenceGenerator(name = "versions_seq", allocationSize = 1)
@Column(name = "id")
private long id;
@Column(name = "name")
private String name;
@Column(name = "creation_time")
private Date creationTime;
@Column(name = "exe_file")
@Lob
private Blob exeFile;
@ManyToMany(mappedBy = "versions", cascade = CascadeType.MERGE)
private Set<MachineGroup> machineGroups = new HashSet<>();
}
@Entity
@Table(name="machine_groups")
@Getter
@Setter
@AllArgsConstructor(access = AccessLevel.PUBLIC)
@NoArgsConstructor
public class MachineGroup {
@Id
@GeneratedValue(strategy= GenerationType.AUTO, generator = "machine_groups_seq")
@SequenceGenerator(name = "machine_groups_seq", allocationSize = 1, initialValue = 2)
@Column(name = "id")
private long id;
@Column(name = "name")
private String name;
@Column(name = "creation_time")
private Date creationTime;
@Column(name = "is_official")
private boolean official;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "machine_properties_id", nullable = false)
private ContinuousIntegrationProperties defaultContinuousIntegrationProperties;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "machine_groups_to_users",
joinColumns = @JoinColumn(name = "machine_group_id"),
inverseJoinColumns = @JoinColumn(name = "user_id"))
private Set<User> users = new HashSet<>();
@ManyToMany(cascade = CascadeType.MERGE)
@JoinTable(name = "machine_groups_to_versions",
joinColumns = @JoinColumn(name = "machine_group_id"),
inverseJoinColumns = @JoinColumn(name = "version_id"))
private Set<Version> versions = new HashSet<>();
}
我的控制器:
@GetMapping("/getByMachineGroupName/{machineGroupName}")
public ResponseEntity<List<MachineGroupToVersionDTO>> getAllVersions(@PathVariable String machineGroupName) {
logger.info("Incoming GetMachineGroupToVersionReport Request. Machine Group Name: {}", machineGroupName);
List<MachineGroupToVersionDTO> omgtv = machineGroupToVersionService.getByMachineGroupName(machineGroupName).stream()
.map(this::convertToDto).collect(Collectors.toList());
return new ResponseEntity<>(omgtv, HttpStatus.OK);
}
当我调试时,我可以看到我的 omgtv 拥有我需要的所有数据,但由于某种原因它无法返回它。
正如您在我的 MachineGroupToVersion 类中看到的那样,我提取了 MachineGroup 和版本,我看到的问题是:
- MachineGroup 引用一组版本,每个版本引用一组 MachineGroup
- 版本类相同
看起来如何创建表是一个循环问题。我尝试使用 @JsonIgnoreProperties 注释,但它只是将其从响应中删除,这不是预期的结果。
我看到了显示错误的跟踪,但我该如何解决这个问题?
through reference chain: java.util.ArrayList[0]->entities.machinegrouptoversion.MachineGroupToVersionDTO[\"machineGroup\"]->entities.machinegroup.MachineGroup[\"users\"]->org.hibernate.collection.internal.PersistentSet[0]->entities.user.User[\"machineGroups\"]
除非我专门调用 get 函数,否则我不想让一切都变得急切。
如何在不改变我的类和数据库结构的情况下解决这个问题?
更新:
服务
- 项目清单
@Transactional(transactionManager = "primaryTransactionManager", propagation= Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)
public List<MachineGroupToVersionDTO> getByMachineGroupName(String mgName) {
List<MachineGroupToVersionDTO> mgtvl = new ArrayList<>();
Optional<MachineGroup> mg = machineGroupService.getByName(mgName);
if(mg.isPresent())
mgtvl = machineGroupToVersionRepository.findByMachineGroup(mg.get()).stream()
.map(this::convertToDto).collect(Collectors.toList());
return mgtvl;
}
private MachineGroupToVersionDTO convertToDto(MachineGroupToVersion mgtv) {
MachineGroupToVersionDTO machineGroupToVersionDTO = new MachineGroupToVersionDTO();
machineGroupToVersionDTO.setMachineGroup(mgtv.getMachineGroup());
machineGroupToVersionDTO.setVersion(mgtv.getVersion());
machineGroupToVersionDTO.setCreationTime(mgtv.getCreationTime());
machineGroupToVersionDTO.setState(mgtv.getState());
machineGroupToVersionDTO.setTestedTime(mgtv.getTestedTime());
return machineGroupToVersionDTO;
}
解决方案
感谢@Shadov,我能够找到问题所在。就我而言,这个问题是我在创建 DTO 时犯的一个错误。
我错误地使用实体而不是其他 DTO 的字段创建了 DTO。一旦我将它们从实体更改为 DTO,我就能够得到我需要的响应。
从此改变:
public class MachineGroupToVersionDTO {
private MachineGroup machineGroup;
private Version version;
private String state;
private Date testedTime;
private Date creationTime;
}
对此:
public class MachineGroupToVersionDTO {
private MachineGroupSimpleDTO machineGroup;
private VersionDTO version;
private String state;
private Date testedTime;
private Date creationTime;
}
推荐阅读
- angular - 基于 Angular Material 版本的课程
- javascript - 反应 - 展开/折叠全部
- azure - 如何修复 azure bot 服务的松弛通道上的验证令牌错误?
- magento - 如何在不使用 magento 1.9 中的任何扩展程序的情况下集成 GOOGLE PAY IN 支付方式?
- java - 将数据从 jsonarray 传递到表视图时出现 onClick 错误
- python-3.x - 为什么我的 font.name 属性不影响使用 Python-pptx 制作的 ppt 上的字体?我总是得到 arial 字体
- algorithm - 在 O(1) 时间内递增键、递减键、查找最大值键、查找最小值键
- python - 如果按钮发送发布请求,如何从网页中抓取 PDF 文件
- excel - 将不相邻的数据单元格复制到一个工作簿中
- regex - 是否可以在 FILTER 函数中添加 IF 函数?