问题:在Spring Boot服务中使用ModelMapper更新从DTO转换的实体时出现问题。

huangapple go评论47阅读模式
英文:

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&lt;PersonDto&gt; 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 = &quot;team_id&quot;)
private List&lt;Person&gt; members = new ArrayList&lt;&gt;();
}
@Data
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
public interface TeamRepository extends ListCrudRepository&lt;TeamEntity, Long&gt; {}
@Configuration
public class ModelMapperConfig {
@Bean
ModelMapper getModelMapper() {
return new ModelMapper();
}
}
@RestController
@RequiredArgsConstructor
public class TeamController {
private final TeamRepository teamRepository;
private final ModelMapper mapper;
@PostMapping(&quot;/team&quot;)
public void create(@RequestBody TeamDto team) {
Team teamEntity = mapper.map(team, Team.class);
teamRepository.save(teamEntity);
}
@PutMapping(&quot;/team/{id}&quot;)
public void update(@RequestBody TeamDto team, @PathVariable Long id) {
Team teamEntity = teamRepository.findById(id).orElseThrow(() -&gt; 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=&quot;all-delete-orphan&quot; 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 -&gt; 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 -&gt; mapper.map(dto, Person.class))
.forEach(teamEntity.getMembers()::add);

huangapple
  • 本文由 发表于 2023年3月31日 23:57:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75900535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定