Mapstruct Одно ко многим отношениям не удастся на картуJAVA

Программисты JAVA общаются здесь
Anonymous
Mapstruct Одно ко многим отношениям не удастся на карту

Сообщение Anonymous »

В процессе создания пружинного приложения, в котором я использую карту Mapstruct для карты между объектом объекта и объектом DTO. Я также использую Lombok, чтобы уменьшить шаблон, хотя я не совсем уверен, что это актуально, но я хотел бы включить его на случай, если это так. Я пошел, чтобы добавить взаимосвязь между объектами, и теперь мой Mapper не работает должным образом, и не останавливает запуск приложения.

Код: Выделить всё


org.mapstruct
mapstruct
1.6.3



org.mapstruct
mapstruct-processor
1.6.3

Рабочий код:

Код: Выделить всё

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Entity
public class Program {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
< /code>
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class ProgramDTO {
private Long id;
@NotNull
private String name;
}
< /code>
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
< /code>
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class StudentDTO {
private Long id;
@NotNull
private String name;
}
< /code>
@Mapper(
componentModel = MappingConstants.ComponentModel.SPRING,
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
uses = {StudentMapper.class}
)
public interface ProgramMapper {
Program toProgram(ProgramDTO programDTO);
ProgramDTO toProgramDTO(Program program);
}
< /code>
@Mapper(
componentModel = MappingConstants.ComponentModel.SPRING,
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
uses = {ProgramMapper.class}
)
public interface StudentMapper {
Student toStudent(StudentDTO studentDTO);
StudentDTO toStudentDTO(Student student);
}
< /code>
Теперь я хотел добавить отношения между этими двумя объектами от одного ко многим, которые создали цикл в Mappers.  В поисках решений онлайн я попробовал несколько, наиболее широко принятой версией была использование CycleavoidingMapingContext 
, чтобы предотвратить повторное приложение навсегда.

Код: Выделить всё

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Entity
public class Program {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(mappedBy = "enrolledProgram", cascade = CascadeType.ALL, orphanRemoval = true)
private Set enrolledStudents;
}
< /code>
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class ProgramDTO {
private Long id;
@NotNull
private String name;
@NotNull
private Set enrolledStudents;
}
< /code>
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "program_id")
private Program enrolledProgram;
}
< /code>
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class StudentDTO {
private Long id;
@NotNull
private String name;
@NotNull
private ProgramDTO enrolledProgram;
}
< /code>
public class CycleAvoidingMappingContext {
private Map knownInstances = new IdentityHashMap();
@BeforeMapping
public  T getMappedInstance(Object source, @TargetType Class targetType) {
return (T) knownInstances.get(source);
}
@BeforeMapping
public void storeMappedInstance(Object source, @MappingTarget Object target) {
knownInstances.put(source, target);
}
}
< /code>
@Mapper(
componentModel = MappingConstants.ComponentModel.SPRING,
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
uses = {StudentMapper.class}
)
public interface ProgramMapper {
Program toProgram(ProgramDTO programDTO, @Context CycleAvoidingMappingContext context);
@InheritInverseConfiguration
ProgramDTO toProgramDTO(Program program, @Context CycleAvoidingMappingContext context);
}
< /code>
@Mapper(
componentModel = MappingConstants.ComponentModel.SPRING,
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
uses = {ProgramMapper.class}
)
public interface StudentMapper {
Student toStudent(StudentDTO studentDTO, @Context CycleAvoidingMappingContext context);
@InheritInverseConfiguration
StudentDTO toStudentDTO(Student student, @Context CycleAvoidingMappingContext context);
}
Тем не менее, несмотря на добавление контекста, приложение не сможет сказать, что у меня есть циклическая ссылка между StudentMapper и Programmapper . Я исследовал эту проблему и пришел к выводу, что это была, вероятно, аннотация @builder из Ломбока, вызывая эту проблему. Верно)) аннотация методам. Тем не менее, ошибка цикла все еще присутствует и не позволит приложению начать. Поэтому я комментирую аннотации застройщика на всех объектах, DTOS и Mappers. Теперь это позволяет запустить приложение, однако картины вообще не отображают каких -либо поля. Все поля являются нулевыми после прохождения в любом направлении процесса картирования. Глядя на сгенерированную реализацию Mapper, я замечаю, что создает новые объекты с пустым конструктором, но никогда не присваивает каких-либо значений полям.@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2025-05-27T08:09:19-0600",
comments = "version: 1.6.3, compiler: javac, environment: Java 24 (Oracle Corporation)"
)
@Component
public class ProgramMapperImpl implements ProgramMapper {

@Override
public Program toProgram(ProgramDTO programDTO, CycleAvoidingMappingContext context) {
Program target = context.getMappedInstance( programDTO, Program.class );
if ( target != null ) {
return target;
}
if ( programDTO == null ) {
return null;
}
Program program = new Program();
context.storeMappedInstance( programDTO, program );
return program;
}

@Override
public ProgramDTO toProgramDTO(Program program, CycleAvoidingMappingContext context) {
ProgramDTO target = context.getMappedInstance( program, ProgramDTO.class );
if ( target != null ) {
return target;
}
if ( program == null ) {
return null;
}
ProgramDTO programDTO = new ProgramDTO();
context.storeMappedInstance( program, programDTO );
return programDTO;
}
}
< /code>
Я пытался найти решения для этого онлайн, но я продолжаю находить ресурсы, которые повторяют вышеуказанные шаги. Я также попытался реализовать несколько других методов, которые я нашел в своем исследовании, но все они поделились одними и теми же результатами (большинство из них все еще бросают циклические ошибки при запуске).
Любая помощь в этом будет высоко оценена.

Подробнее здесь: https://stackoverflow.com/questions/796 ... ing-to-map

Вернуться в «JAVA»