Mapstruct - 如何将 DTO 字符串参数转换为实体对象?
Mapstruct - How to convert a DTO String parameter to an Entity object?
我是 Mapstruct 的新手,我正在努力正确理解它。
我想要实现的是从 DTO 字符串参数(carModel)转换为他的实体,使用服务和存储库检索。
问题是 Mapstruct 生成的 Mapper class 试图用 @Autowired
注释注入服务 class,但它不起作用。该服务为空。
这是我的 @Mapper
class:
@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
class:
@Service
@Transactional
public class CarModelService {
private final CarModelRepository carModelRepository;
@Transactional(readOnly = true)
public CarModel findByName(String name) {
return carModelRepository.findByName(name).orElse(null);
}
}
@Repository
class:
@Repository
public interface CarModelRepository extends JpaRepository<CarModel, Long> {
Optional<CarModel> findByName(String carModelName);
}
DTO 和实体 classes:
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 为空。
这是映射器生成的实现 class:
@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;
}
}
我尝试了很多东西,使用装饰器、@Context、表达式,将@Mapper class 注入@Service class。
我发现了很多问题,但实际上没有人帮助我:
MapStruct mapper not initialized with autowired when debug
如有任何帮助,我们将不胜感激!提前致谢!
能否分享错误信息?
从你分享的信息,我可以看到KitDto中的carModel是String,Entity中的是CarModel class。不确定 mapstruct 的自动生成实现 class 是如何实现的:kit.carModel( carModelService.findByName(kitDTO.getCarModel()) );
.
但我想分享另一种方法,不知道这是否是最佳做法。在这种方法中,您可以创建一个 abstarct class 映射器,您可以在其中 @Autowired 存储库可以手动添加那些映射。
我分享了它的片段。希望这对你有所帮助。
@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;
}
}
对其他方法感到好奇,将关注此线程。我们可以讨论最佳实践
找到解决方案!
我没有直接从 @RestController
class 调用 Mapper 方法 toEntity()
,而是在 CarModelService
class 中注入了映射器并创建了一个方法调用映射器。
这样的流程是:
Controller --> Service --> 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生成的class就不会在CarModelService上报错了。
似乎这种方法是实现此目的的唯一方法,在服务和映射器之间创建“桥梁”之王。
(您也可以使用 @Autowired
注释而不是构造函数)
我是 Mapstruct 的新手,我正在努力正确理解它。
我想要实现的是从 DTO 字符串参数(carModel)转换为他的实体,使用服务和存储库检索。
问题是 Mapstruct 生成的 Mapper class 试图用 @Autowired
注释注入服务 class,但它不起作用。该服务为空。
这是我的 @Mapper
class:
@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
class:
@Service
@Transactional
public class CarModelService {
private final CarModelRepository carModelRepository;
@Transactional(readOnly = true)
public CarModel findByName(String name) {
return carModelRepository.findByName(name).orElse(null);
}
}
@Repository
class:
@Repository
public interface CarModelRepository extends JpaRepository<CarModel, Long> {
Optional<CarModel> findByName(String carModelName);
}
DTO 和实体 classes:
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 为空。 这是映射器生成的实现 class:
@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;
}
}
我尝试了很多东西,使用装饰器、@Context、表达式,将@Mapper class 注入@Service class。
我发现了很多问题,但实际上没有人帮助我:
MapStruct mapper not initialized with autowired when debug
如有任何帮助,我们将不胜感激!提前致谢!
能否分享错误信息?
从你分享的信息,我可以看到KitDto中的carModel是String,Entity中的是CarModel class。不确定 mapstruct 的自动生成实现 class 是如何实现的:kit.carModel( carModelService.findByName(kitDTO.getCarModel()) );
.
但我想分享另一种方法,不知道这是否是最佳做法。在这种方法中,您可以创建一个 abstarct class 映射器,您可以在其中 @Autowired 存储库可以手动添加那些映射。 我分享了它的片段。希望这对你有所帮助。
@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;
}
}
对其他方法感到好奇,将关注此线程。我们可以讨论最佳实践
找到解决方案!
我没有直接从 @RestController
class 调用 Mapper 方法 toEntity()
,而是在 CarModelService
class 中注入了映射器并创建了一个方法调用映射器。
这样的流程是:
Controller --> Service --> 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生成的class就不会在CarModelService上报错了。
似乎这种方法是实现此目的的唯一方法,在服务和映射器之间创建“桥梁”之王。
(您也可以使用 @Autowired
注释而不是构造函数)