
Olá queridos leitores! Aqueles que desenvolvem aplicativos Java Web usando a estrutura Spring, aqueles que comentam sobre esses aplicativos e estão apenas interessados.
Em um artigo anterior,
“Solucionando problemas de inicialização com o ManyToMany”Dei um exemplo de aplicativo de teste no qual existe um relacionamento bidirecional ManyToMany entre duas classes. O artigo deu um exemplo de solução do problema de loop ao receber uma resposta de descanso usando a classe DTO. Os leitores nos comentários sugeriram o uso da biblioteca
MapStruct para resolver o
problema de loop.
Depois de revisar a
documentação, eu estava convencido de que isso é realmente uma coisa poderosa, com a qual você pode resolver tarefas bastante complexas de mover dados entre objetos. O MapStruct também resolve o problema de loop.
Neste artigo, darei um exemplo de solução do mesmo problema que um aplicativo Spring Boot usando a biblioteca MapStruct.
Código fonte disponível no Github
As pessoas da entidade e os SongPlayers permaneceram inalterados. Getters e setters abaixados.
@Entity public class People { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String human;
@Entity public class SongPlayers { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String song;
Também criamos interfaces de repositório para as classes People e SongPlayers.
@Repository public interface PeopleRepository extends JpaRepository<People, Long> { @Query("select h from People h where h.human=?1") List<People> searchByHuman(String human); List<People> findPeopleByHuman(String human); }
@Repository public interface SongPlayersRepository extends JpaRepository<SongPlayers, Long> { List<SongPlayers> findSongPlayersBySong(String song); List<SongPlayers> findSongPlayersByComposer(String composer); List<SongPlayers> findSongPlayersByPoet(String poet); }
Também criamos classes de DTO para People e SongPlayers, que agora não parecem tão volumosas. Getters e setters eu abaixo.
public class PeopleDTO { private long id; private String human; private RockGroups rockGroups; private List<SongPlayersDTO> songPlayersList;
public class SongPlayersDTO { private long id; private String song; private String composer; private String poet; private String album;
Para descrever a regra para transferir dados do objeto de origem para o objeto DTO e, se necessário, criamos interfaces de mapeador para cada classe que requer proteção de loop. Aqui estão os PeopleMapper e SongPlayersMapper
@Mapper(uses = SongPlayersMapper.class) public interface PeopleMapper { PeopleMapper PEOPLE_MAPPER = Mappers.getMapper(PeopleMapper.class); @Mapping(source = "songItems", target = "songPlayersList") PeopleDTO fromPeople(People people); }
@Mapper public interface SongPlayersMapper { SongPlayersMapper SONG_PLAYERS_MAPPER = Mappers.getMapper(SongPlayersMapper.class); SongPlayersDTO fromSongPlayers(SongPlayers songPlayers); @InheritInverseConfiguration SongPlayers toSongPlayers(SongPlayersDTO songPlayersDTO); }
Na pasta Serviço, crie as interfaces e a implementação das classes de serviço, nas quais colocamos os métodos de recebimento de dados (eu darei para Pessoas).
public interface PeopleService { List<PeopleDTO> getAllPeople(); PeopleDTO getPeopleById(long id); People addPeople(People people); void delPeople(long id); ResponseEntity<Object> updPeople(People people, long id); List<RockGroups> getByHuman(String human); List<String> getSongByHuman(String human); }
@Service("peopleservice") public class PeopleServiceImpl implements PeopleService { @Autowired private PeopleRepository repository; @Override public List<PeopleDTO> getAllPeople() { List<PeopleDTO> peopleDTOList = new ArrayList<>(); List<People> peopleList = repository.findAll(); for (People people : peopleList){ peopleDTOList.add(PeopleMapper.PEOPLE_MAPPER.fromPeople(people)); } return peopleDTOList; }
Nos controladores, aplicaremos esses métodos adequadamente (novamente apenas para Pessoas)
@RestController @RequestMapping("/people") public class PeopleController { @Autowired private PeopleServiceImpl service; @GetMapping("/all") public List<PeopleDTO> getAllPeople(){ return service.getAllPeople(); }
Na solução acima do problema de loop para a relação ManyToMany, posso dizer que a opção com classes DTO do artigo anterior e a versão com a biblioteca MapStruct deste artigo também estão funcionando. Comparada com a versão anterior, a classe DTO foi bastante simplificada, mas as interfaces do Mapper foram adicionadas. Em geral, qualquer método pode ser usado; em casos simples, eu estaria inclinado à primeira opção.
Agradeço a todos os participantes da discussão. Aguardando seus comentários.
Link
para o artigo anterior .
Link
para o projeto no Github .
Literatura usada:
- Bota de primavera Felipe Gutierrez Pro
- Craig Walls Spring em ação 5ª edição