I have Student class with @OneToMany relationship to classes like below
public class Student {
@Id
@GeneratedValue
private Long id;
//fields
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "class_id")
private Class classEntity;
And class entity:
public class Class {
@Id
@GeneratedValue
private Long id;
//fields
@EqualsAndHashCode.Exclude
@ToString.Exclude
@OneToMany(mappedBy = "classEntity", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Set<Student> students;
I'm using MapStruct to convert dto to entity and entity to dto:
StudentMapper.java
@Mapper(componentModel = "spring", uses = {ClassMapper.class})
public interface StudentMapper extends EntityMapper<StudentDTO, Student> {
@Mapping(source = "classEntity.id", target="classId")
@Mapping(source = "classEntity.name", target="className")
StudentDTO toDto(Student student);
@Mapping(source = "classId", target="classEntity.id")
Student toEntity(StudentDTO studentDTO);
default Student fromId(Long id) {
if (id == null) {
return null;
}
Student entity = new Student();
entity.setId(id);
return entity;
}
default Long toId(Student student) {
if (student == null){
return null;
}
return student.getId();
}
ClassMapper.java
@Mapper(componentModel = "spring")
public interface ClassMapper extends EntityMapper<ClassDTO, Class> {
@Mapping(target = "educatorId" , source = "educator.id")
ClassDTO toDto(Class classEntity);
@Mapping(target = "educator.id" , source = "educatorId")
Class toEntity(ClassDTO classDTO);
default Class fromId(Long id) {
if (id == null) {
return null;
}
Class entity = new Class();
entity.setId(id);
return entity;
}
default Long toId(Class classEntity) {
if (classEntity == null){
return null;
}
return classEntity.getId();
}
}
These mappers extends simple EntityMapper interface
public interface EntityMapper <D, E> {
E toEntity (D dto);
D toDto(E entity);
List <E> toEntity (List<D> dtoList);
List<D> toDto (List<E> entityList);
Set <E> toEntity (Set<D> dtoSet);
Set<D> toDto (Set<E> entitySet);
Generated StudentMapperImpl.class
public Student toEntity(StudentDTO studentDTO) {
if ( studentDTO == null ) {
return null;
}
StudentBuilder student = Student.builder();
student.classEntity( studentDTOToClass( studentDTO ) );
//fields
return student.build();
}
protected Class studentDTOToClass(StudentDTO studentDTO) {
if ( studentDTO == null ) {
return null;
}
Class class1 = new Class();
class1.setId( studentDTO.getClassId() );
return class1;
}
Everything works fine when I'm trying to convert studentDTO to student entity with filled classId in studentDTO class. The problem starts when classId in studentDTO is null. Then mapper create new Class Objects and saving it into database....
And don't want this because not every student will have assigned class. I've tried everything with CascadeType in Student.class but I think the problem is in my MapStruct mapper.
Eventually I can write my own mappers without mapstruct but I'd rather avoid it. Please help me.