我是Mapstruct的新手,我正在努力正确理解它。
我想要实现的是从DTO字符串参数(carModel)转换为他的实体,使用服务和存储库进行检索。
问题是Mapstruct生成的Mapper类试图用@Autowired
注释注入Service类,但它不起作用。服务为null。
这是我的@Mapper
类:
@Mapper(componentModel = "spring", uses = CarModelService.class)
public interface KitMapper extends EntityMapper<KitDTO, Kit> {
KitMapper INSTANCE = Mappers.getMapper(KitMapper.class);
@Mapping(source = "weight", target = "systemWeight")
@Mapping(source = "carModel", target = "carModel")
Kit toEntity(KitDTO kitDTO);
}
public interface EntityMapper<D, E> {
E toEntity(D dto);
List<E> toEntity(List<D> dtoList);
}
@Service
类:
@Service
@Transactional
public class CarModelService {
private final CarModelRepository carModelRepository;
@Transactional(readOnly = true)
public CarModel findByName(String name) {
return carModelRepository.findByName(name).orElse(null);
}
}
@Repository
类:
@Repository
public interface CarModelRepository extends JpaRepository<CarModel, Long> {
Optional<CarModel> findByName(String carModelName);
}
DTO和实体类:
public class KitDTO {
private String id;
private String carModel; // e.g. "Ferrari Monza"
....
}
@Entity
@Table(name = "kit")
public class Kit implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@Column(name = "id")
private Long id;
@ManyToOne
private CarModel carModel;
...
}
@Entity
@Table(name = "car_model")
public class CarModel implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
...
}
构建工作正常,但当我尝试使用Mapper时,应用程序会停止。它说carModelService为空。以下是映射程序生成的实现类:
@Component
public class KitMapperImpl implements KitMapper {
@Autowired // <-- this seems not working
private CarModelService carModelService;
@Override
public Kit toEntity(KitDTO kitDTO) {
if ( kitDTO == null ) {
return null;
}
Kit kit = new Kit();
kit.setSystemWeight( String.valueOf( kitDTO.getWeight() ) );
kit.carModel( carModelService.findByName(kitDTO.getCarModel()) ); // <-- carModelService is null!
// other setters
return kit;
}
}
我已经尝试了很多方法,使用Decorator、@Context、expression,将@Mapper类注入@Service类。
我发现了很多问题,但实际上没有人帮我:
Mapstruct-如何在Generated Mapper类中注入spring依赖项
@服务类未在org.mapstruct.@Mapper Class 中自动连接
调试时,MapStruct映射器未使用autowired进行初始化
任何帮助都将不胜感激!提前感谢!
找到了解决方案!
我没有从@RestController
类直接调用Mapper方法toEntity()
,而是在CarModelService
类中注入了Mapper,并创建了一个调用Mapper的方法。通过这种方式,流程是:
控制器-->服务-->映射器
@Service
@Transactional
public class KitService {
private final KitRepository kitRepository;
private final KitSearchRepository kitSearchRepository;
private final KitMapper kitMapper; // <-- mapper declaration
public KitService(KitRepository kitRepository, KitSearchRepository kitSearchRepository, KitMapper kitMapper) {
this.kitRepository = kitRepository;
this.kitSearchRepository = kitSearchRepository;
this.kitMapper = kitMapper; // <-- mapper initilization
}
// here the method which calls mapper
public Kit convertDTOToEntity(KitDTO kitDTO) {
return kitMapper.toEntity(kitDTO);
}
通过这种方式,Mapstruct生成的类不会在CarModelService上产生错误。
看来这种方法是实现这一点的唯一途径,创造一个"王者";"桥";在服务和映射器之间。
(您也可以使用@Autowired
注释而不是构造函数)
您能分享错误消息吗?从您共享的信息中,我可以看到KitDto中的carModel是String,Entity中的carModel是carModel类。不确定mapstruct的自动生成的实现类是如何实现的:kit.carModel( carModelService.findByName(kitDTO.getCarModel()) );
。
但我想分享另一种方法,不知道这是否是最佳实践。在这种方法中,您可以创建一个abstract类的mapper,在其中您可以@Autowired repository手动添加这些映射。我分享了它的片段。希望这能对你有所帮助。
@Mapper(componentModel = "spring", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public abstract class ProductMapper {
@Autowired
private CarModelService carModelService;
public abstract Kit convertDTOToEntity(KitDTO kitDTO);
public Kit toEntity(KitDTO kitDTO);
{
Kit kit = convertDTOToEntity(kitDTO);
kit.setCarModel(carModelService.findByName(kitDTO.getCarModel()));
return kit;
}
}
对其他方法感到好奇,将遵循此线索。我们可以讨论的最佳实践