Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
311 views
in Technique[技术] by (71.8m points)

java - Update an entity with bidirectional relationship and using ModelMapper - exception

So my problem is updating Subjects in Class, I get an exception. What do you think may be the reason and can you explain how can I solve my problem (for dummies, please). I was thinking changing modelmapper config but I will always have the subjects in my classes and classes in my subjects that way and the problem persists. But on the other hand I prefer to leave the relationship like so (not to create SQL with joins - I prefer using FKs). But in the end the question still exists - how do you propose I solved this problem? Thanks in advance!

@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "classes")
public class Class {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotNull
    private String name;

    @OneToOne(mappedBy = "myClass")
    private Teacher headTeacher;
    @OneToMany
    private List<Student> students;
    @OneToMany(mappedBy = "myClass")
    private List<Subject> subjects;

    @Builder
    private Class(final Long id,
                  final String name,
                  final Teacher headTeacher,
                  final List<Student> students,
                  final List<Subject> subjects){
        checkArgument(!Strings.isNullOrEmpty(name), "name cannot be null or empty");
        checkArgument(headTeacher != null, "headTeacher cannot be null");
        this.id = id;
        this.name = name;
        this.headTeacher = headTeacher;
        this.students = students;
        this.subjects = subjects;
    }
}
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "subjects")
@ToString(exclude = "myClass")
@EqualsAndHashCode(exclude = "myClass")
public class Subject {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToOne
    private Teacher teacher;
    @ManyToMany
    private Set<Teacher> replacingTeachers;
    @ManyToOne
    @JoinColumn(name = "class_id")
    private Class myClass;

    @Builder
    private Subject(final Long id,
                    final String name,
                    final Teacher teacher,
                    final Set<Teacher> replacingTeachers,
                    final Class myClass){
        checkArgument(!Strings.isNullOrEmpty(name), "name cannot be null or empty");
        checkArgument(teacher != null, "teacher cannot be null");
        this.id = id;
        this.name = name;
        this.teacher = teacher;
        this.replacingTeachers = replacingTeachers;
        this.myClass = myClass;
    }
}
@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ClassDto {

    private Long id;
    @NotBlank
    private String name;

    private TeacherDto headTeacher;
    private List<StudentDto> students;
    @JsonManagedReference
    private List<SubjectDto> subjects;

    @Builder
    @JsonCreator
    private ClassDto(@JsonProperty("id") final Long id,
                    @JsonProperty("name") final String name,
                    @JsonProperty("headTeacher") final TeacherDto headTeacher,
                    @JsonProperty("students") final List<StudentDto> students,
                    @JsonProperty("subjects") final List<SubjectDto> subjects){
        this.id = id;
        this.name = name;
        this.headTeacher = headTeacher;
        this.students = students;
        this.subjects = subjects;
    }
}
@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@ToString(exclude = "myClass")
@EqualsAndHashCode(exclude = "myClass")
public class SubjectDto {

    private Long id;
    @NotBlank
    private String name;

    @NotNull
    private TeacherDto teacher;
    private Set<TeacherDto> replacingTeachers;
    @JsonBackReference
    private ClassDto myClass;

    @Builder
    @JsonCreator
    private SubjectDto(@JsonProperty("id") final Long id,
                       @JsonProperty("name") final String name,
                       @JsonProperty("teacher") final TeacherDto teacher,
                       @JsonProperty("replacingTeachers") final Set<TeacherDto> replacingTeachers,
                       @JsonProperty("myClass") final ClassDto myClass){
        this.id = id;
        this.name = name;
        this.teacher = teacher;
        this.replacingTeachers = replacingTeachers;
        this.myClass = myClass;
    }
}

    @Transactional
    public ClassDto update(final ClassDto classDto) throws NoSuchElementException {
        log.info("Altering class: " + classDto.toString());

        Class aClass = repository.findById(classDto.getId())
                .orElseThrow(() -> new NoSuchElementException("No class with id " + classDto.getId() + " was found"));
        modelMapper.map(classDto, aClass);

        return modelMapper.map(repository.save(aClass), ClassDto.class);
    }
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.modelmapper.MappingException: ModelMapper mapping errors:

1) Converter org.modelmapper.internal.converter.MergingCollectionConverter@1cf94666 failed to convert java.util.ArrayList to java.util.List.

1 error] with root cause

org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) The destination property io.soft.ejournal.entity.Subject.setTeacher()/io.soft.ejournal.entity.person.Teacher.setMyClass()/io.soft.ejournal.entity.Class.setName() matches multiple source property hierarchies:

    io.soft.ejournal.dto.SubjectDto.getMyClass()/io.soft.ejournal.dto.ClassDto.getHeadTeacher()/io.soft.ejournal.dto.person.PersonDto.getMiddleName()
    io.soft.ejournal.dto.SubjectDto.getMyClass()/io.soft.ejournal.dto.ClassDto.getHeadTeacher()/io.soft.ejournal.dto.person.PersonDto.getLastName()
    io.soft.ejournal.dto.SubjectDto.getMyClass()/io.soft.ejournal.dto.ClassDto.getHeadTeacher()/io.soft.ejournal.dto.person.PersonDto.getFirstName()

1 error
    at org.modelmapper.internal.Errors.throwConfigurationExceptionIfErrorsExist(Errors.java:241) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.ImplicitMappingBuilder.matchDestination(ImplicitMappingBuilder.java:158) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.ImplicitMappingBuilder.matchDestination(ImplicitMappingBuilder.java:151) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.ImplicitMappingBuilder.matchDestination(ImplicitMappingBuilder.java:151) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.ImplicitMappingBuilder.build(ImplicitMappingBuilder.java:89) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.ImplicitMappingBuilder.build(ImplicitMappingBuilder.java:74) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.TypeMapStore.getOrCreate(TypeMapStore.java:128) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.TypeMapStore.getOrCreate(TypeMapStore.java:102) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:113) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.converter.MergingCollectionConverter.convert(MergingCollectionConverter.java:59) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.converter.MergingCollectionConverter.convert(MergingCollectionConverter.java:31) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.convert(MappingEngineImpl.java:303) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:110) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.setDestinationValue(MappingEngineImpl.java:242) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.propertyMap(MappingEngineImpl.java:188) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:152) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:106) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:72) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.ModelMapper.mapInternal(ModelMapper.java:573) ~[modelmapper-2.3.9.jar:na]
    at org.modelmapper.ModelMapper.map(ModelMapper.java:447) ~[modelmapper-2.3.9.jar:na]
    at io.soft.ejournal.service.ClassService.update(ClassService.java:65) ~[classes/:na]
    at io.soft.ejournal.service.ClassService$$FastClassBySpringCGLIB$$783efd16.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:123) ~[spring-context-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.2.jar:5.3.2]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.2.jar:5.3.2]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.3.2.jar:5.3.2]
    at io.soft.ejournal.service.ClassService$$EnhancerBySpringCGLIB$$bd8a181c.update(<generated>) ~[classes/:na]
    at io.soft.ejournal.controller.ClassController.update(ClassController.java:106) ~[classes/:na]
    at io.soft.ejournal.controller.ClassController$$FastClassBySpringCGLIB$$2162dd02.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.3.2.jar:5.3.2]
    at org.springframework.security.access.intercept.aopalliance.MethodSe

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...