英文:
Issue updating Entity converted from DTO using ModelMapper in Spring Boot Service
问题
I am building a Spring Boot Service and trying to use ModelMapper to convert between DTO and Entity, but hitting issues on update. Here is a simplified example:
@Data
public class TeamDto {
private String name;
private List<PersonDto> members;
}
@Data
public class PersonDto {
private String name;
}
@Data
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
@JoinColumn(name = "team_id")
private List<Person> members = new ArrayList<>();
}
@Data
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
public interface TeamRepository extends ListCrudRepository<TeamEntity, Long> {}
@Configuration
public class ModelMapperConfig {
@Bean
ModelMapper getModelMapper() {
return new ModelMapper();
}
}
@RestController
@RequiredArgsConstructor
public class TeamController {
private final TeamRepository teamRepository;
private final ModelMapper mapper;
@PostMapping("/team")
public void create(@RequestBody TeamDto team) {
Team teamEntity = mapper.map(team, Team.class);
teamRepository.save(teamEntity);
}
@PutMapping("/team/{id}")
public void update(@RequestBody TeamDto team, @PathVariable Long id) {
Team teamEntity = teamRepository.findById(id).orElseThrow(() -> new ResponseStatusException(NOT_FOUND));
mapper.map(team, teamEntity);
teamRepository.save(teamEntity);
}
}
I am able to create a team, but when I try to update, I get an error saying: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: org.aero.cvr.TeamEntity.members.
I'm not sure how best to address this error.
英文:
I am building a Spring Boot Service and trying to use ModelMapper to convert between DTO and Entity, but hitting issues on update. Here is a simplified example:
@Data
public class TeamDto {
private String name;
private List<PersonDto> members;
}
@Data
public class PersonDto {
private String name;
}
@Data
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
@JoinColumn(name = "team_id")
private List<Person> members = new ArrayList<>();
}
@Data
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
public interface TeamRepository extends ListCrudRepository<TeamEntity, Long> {}
@Configuration
public class ModelMapperConfig {
@Bean
ModelMapper getModelMapper() {
return new ModelMapper();
}
}
@RestController
@RequiredArgsConstructor
public class TeamController {
private final TeamRepository teamRepository;
private final ModelMapper mapper;
@PostMapping("/team")
public void create(@RequestBody TeamDto team) {
Team teamEntity = mapper.map(team, Team.class);
teamRepository.save(teamEntity);
}
@PutMapping("/team/{id}")
public void update(@RequestBody TeamDto team, @PathVariable Long id) {
Team teamEntity = teamRepository.findById(id).orElseThrow(() -> new ResponseStatusException(NOT_FOUND));
mapper.map(team, teamEntity);
teamRepository.save(teamEntity);
}
}
I am able to create a team, but when I try to update, I get an error saying: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: org.aero.cvr.TeamEntity.members.
I'm not sure how best to address this error.
答案1
得分: 1
Here is the translated code portion:
最佳解决方案是不使用ModelMapper来处理成员列表,而是让它跳过该字段:
@Bean
ModelMapper getModelMapper() {
ModelMapper mapper = new ModelMapper();
mapper.typeMap(TeamDto.class, TeamEntity.class)
.addMappings(mp -> mp.skip(TeamEntity::setMembers));
return mapper;
}
然后手动处理该字段,更新现有列表,而不是让ModelMapper替换它,但仍然在列表中使用ModelMapper处理对象:
teamEntity.getMembers().clear();
teamDto.getMembers().stream().map(dto -> mapper.map(dto, Person.class))
.forEach(teamEntity.getMembers()::add);
英文:
Best solution I've come up with is to not use ModelMapper to handle the members list. Instead, have it skip that field:
@Bean
ModelMapper getModelMapper() {
ModelMapper mapper = new ModelMapper();
mapper.typeMap(TeamDto.class, TeamEntity.class)
.addMappings(mp -> mp.skip(TeamEntity::setMembers));
return mapper;
}
and to handle the field manually, updating the existing list, rather than letting ModelMapper replace it, but still using ModelMapper on the objects in the list:
teamEntity.getMembers().clear();
teamDto.getMembers().stream().map(dto -> mapper.map(dto, Person.class))
.forEach(teamEntity.getMembers()::add);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论