MapStruct-Problemlösung mit ManyToMany



Hallo liebe Leser! Diejenigen, die Java-Webanwendungen mit dem Spring-Framework entwickeln, diejenigen, die diese Anwendungen kommentieren und nur interessiert sind.

In einem früheren Artikel, "Spring Boot Problemlösung mit ManyToMany"

Ich habe ein Beispiel für eine Testanwendung gegeben, in der zwischen zwei Klassen eine bidirektionale Beziehung ManyToMany besteht. Der Artikel gab ein Beispiel für die Lösung des Schleifenproblems beim Empfang einer Ruhe-Antwort mit der DTO-Klasse. Leser in den Kommentaren schlugen vor, die MapStruct- Bibliothek zu verwenden, um das Schleifenproblem zu lösen .

Nach Durchsicht der Dokumentation war ich überzeugt, dass dies wirklich eine leistungsstarke Sache ist, mit der Sie ziemlich komplexe Aufgaben beim Verschieben von Daten zwischen Objekten lösen können. MapStruct löst auch das Schleifenproblem.

In diesem Artikel werde ich ein Beispiel für die Lösung des gleichen Problems wie eine Spring Boot-Anwendung unter Verwendung der MapStruct-Bibliothek geben. Quellcode bei Github erhältlich

Entity People und SongPlayers blieben unverändert. Getter und Setter gesenkt.

@Entity public class People { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String human; //      @ManyToOne(cascade = CascadeType.ALL) private RockGroups rockGroups; //     @ManyToMany(mappedBy = "songInstrumentalist",fetch = FetchType.EAGER) private List<SongPlayers> songItems; public People(){} public People(long id, String human){ this.id = id; this.human = human; } //. . . . . } 

 @Entity public class SongPlayers { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String song; //    private String composer; //     private String poet; //    private String album; //   //     @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) private List<People> songInstrumentalist; //. . . . . } 

Wir erstellen auch Repository-Schnittstellen für die Klassen People und 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); } 

Wir erstellen auch DTO-Klassen für People und SongPlayers, die jetzt nicht mehr so ​​umfangreich aussehen. Getter und Setter senke ich.

 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; // . . . . . } 

Um die Regel für die Übertragung von Daten vom Quellobjekt zum DTO-Objekt und gegebenenfalls zurück zu beschreiben, erstellen wir Mapper-Schnittstellen für jede Klasse, für die ein Schutz gegen Schleifen erforderlich ist. Hier sind der PeopleMapper und der 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/*(uses = {PeopleMapper.class})*/ public interface SongPlayersMapper { SongPlayersMapper SONG_PLAYERS_MAPPER = Mappers.getMapper(SongPlayersMapper.class); SongPlayersDTO fromSongPlayers(SongPlayers songPlayers); @InheritInverseConfiguration SongPlayers toSongPlayers(SongPlayersDTO songPlayersDTO); } 

Erstellen Sie im Ordner "Service" die Schnittstellen und die Implementierung von Serviceklassen, in die wir die Methoden zum Empfangen von Daten einfügen (ich werde sie für Personen angeben).

 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; } // . . . . . } 

In Controllern werden wir diese Methoden entsprechend anwenden (wiederum nur für Personen).

 @RestController @RequestMapping("/people") public class PeopleController { @Autowired private PeopleServiceImpl service; @GetMapping("/all") public List<PeopleDTO> getAllPeople(){ return service.getAllPeople(); } // . . . . . } 

Aus der obigen Lösung des Schleifenproblems für die ManyToMany-Beziehung kann ich sagen, dass die Option mit DTO-Klassen aus dem vorherigen Artikel und die Version mit der MapStruct-Bibliothek aus diesem Artikel ebenfalls funktionieren. Im Vergleich zur Vorgängerversion wurde die DTO-Klasse stark vereinfacht, es wurden jedoch Mapper-Schnittstellen hinzugefügt. Im Allgemeinen kann jede Methode verwendet werden, für einfache Fälle würde ich zur ersten Option neigen.

Ich danke allen Teilnehmern der Diskussion. Warten auf Ihre Kommentare.

Link zum vorherigen Artikel .

Link zum Projekt auf Github .

Gebrauchte Literatur:

  • Felipe Gutierrez Pro Spring Boot
  • Craig Walls Spring in Aktion 5. Auflage

Source: https://habr.com/ru/post/de433270/


All Articles