如何使用 mapstruct 将 enum 转换为 POJO 而无需自定义实现?
例如
enum Type {
T1, T2;
private String description;
private Type(String description) {
this.description = description;
}
public String getDescription() { return this.description; }
}
Run Code Online (Sandbox Code Playgroud)
POJO之类的
class TypeDto {
private Type code;
private String description;
}
Run Code Online (Sandbox Code Playgroud)
仅供参考,我使用 MapStruct 1.1.0.Final。
对于想要直接返回实体类的 Web 服务开发人员来说,这是一个常见问题。即使加载了我需要的所有数据,仍然有许多我不需要的未初始化的代理和集合。我希望他们只返回 null 而不是抛出延迟加载异常。基本上我只想要 POJO 合约,但是必须清除代理和休眠集合才能获得它(除非休眠中有一些我不知道的新方法)。我可以使用 MapStruct 来执行此操作吗?
如果需要的话,可以了解更多详细信息:
http://www.mojavelinux.com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/
http://www.gwtproject.org/articles/using_gwt_with_hibernate.html
吉利德是我发现的唯一对此有效的药物,但它已不再存在。
我编写了一个使用如下映射的映射结构映射器:
@Mapping(target = "userId", source = "id.userId")
Run Code Online (Sandbox Code Playgroud)
当我查看自动生成的映射结构类时,我偶然发现了该代码:
if ( !foobar.hasId() ) {
return null;
}
Run Code Online (Sandbox Code Playgroud)
这对我来说是一个问题,因为这hasId()不是 mapstruct 所期望的。我可以以某种方式强制 mapstruct 不生成使用此方法但检查id != null或其他内容的代码吗?
我可以使用类似的映射@Mapping(target = "userId", expression= "java(...)"),但我认为应该有另一种方法。
我想映射嵌套的java对象。Customer.address.houseNumber到userDTO.homeDTO.addressDTO.houseNo。
期望: 当且仅当 Customer.address.houseNumber 不为 null 时,才homeDTO在 下创建对象userDTO。否则,不要创建任何目标对象。
问题: 我已经"NullValueCheckStrategy.ALWAYS"在映射器中使用了,但是mapstruct正在检查是否address不为空,然后它会创建homeDTO. 里面address,houseNumber就是null。我想要空检查直到houseNumber(叶/最后一级对象),然后创建目标对象。
我怎样才能实现这个目标?
这是我正在使用的映射。
@Mapper( nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS )
public interface Customer2UserMapper {
@Mapping(source="address.houseNumber", target="homeDTO.addressDTO.houseNo" )
void mapCustomerHouse(Customer customer, @MappingTarget UserDTO userDTO) ;
}
Run Code Online (Sandbox Code Playgroud)
我有 2 个对象 ExpertJpa 到 ExpertDto 的现有映射,需要另一个参数来过滤 ExpertJpa。该地图工作正常,现在我尝试将 ExpertJpa 列表转换为 ExpertDto 列表,我添加第二个参数。
@Mappings({
@Mapping(target = "status", ignore = true),
@Mapping(target = "profile", source = "input.expertProfile"),
@Mapping(target = "engagementId", expression = "java(new MapperHelper().ReturnExpertEngagementIdByApiKey(input,identity))"),
@Mapping(target = "campaignId", expression = "java(new MapperHelper().ReturnExpertCampaignIdByApiKey(input,identity))"),
})
Expert ExpertJpaToExpert(com.consumer.expert.dbaccessor.entities.Expert input, Identity identity);
List<Expert> ListExpertsJpaToListExperts(List<com.consumer.expert.dbaccessor.entities.Expert> input, Identity identity);
Run Code Online (Sandbox Code Playgroud)
在构建时,我收到错误消息,指出 List 是一个接口,不能是实例......
错误:(53, 18) java:返回类型 java.util.List 是抽象类或接口。提供非抽象/非接口结果类型或工厂方法。
我正在尝试将 mapstruct 与 Gradle 一起使用,但取得的成功有限。当我在应用程序中使用它时,一切似乎都工作正常,但是当我尝试编写一些测试时,Spring 无法正确自动装配 MapStruct (它只返回 NullPointer 异常)。我正在使用 Gradle 5.4.1、Junit5 和 IntelliJ 2019.1.2。
这是构建文件夹,没有为测试类生成映射器。

包含代码的存储库位于: https://github.com/MirkoManojlovic/mapstruct-example
@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN,
componentModel = "spring",
injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface ItemMapper {
ItemDto toDto(Item item);
Item toItem(ItemDto itemDto);
}
Run Code Online (Sandbox Code Playgroud)
public class ItemRepository {
public ItemDto getItemDto() {
return new ItemDto("item 1");
}
public Item getItem() {
return new Item(1, "item 1", 20);
}
}
Run Code Online (Sandbox Code Playgroud)
@Service
@RequiredArgsConstructor
@Log4j2
public class ItemService {
private final ItemRepository itemRepository;
private final ItemMapper …Run Code Online (Sandbox Code Playgroud) 我有以下结构。我的子类中的属性不会复制到我的 DTO 中。
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
class BaseClass
{
private Integer baseProperty1;
private Integer baseProperty2;
//getters & setters
}
class SubClass extends BaseClass
{
private Integer subProperty1;
private Integer subProperty2;
//getters & setters
}
class BaseSubDTO
{
private Integer baseProperty1;
private Integer baseProperty2;
private Integer subProperty1;
private Integer subProperty2;
//getters & setters
}
class BaseClassService
{
public BaseClass find()
{
return baseClassRepository.findById(101);
}
}
class BaseClassController
{
public BaseSubDTO find()
{
return mapper.toDTO(baseClassService.find());
}
}
@Mapper(componentModel = "spring")
public …Run Code Online (Sandbox Code Playgroud) 我有一个类层次结构:VehicleDTO是一个基本抽象类。
CarDTO, TruckDTO, VanDTO从它延伸出来。
我在映射器的另一侧有相同的层次结构:
VehicleBO <- CarBO, TruckBO, VanBO。
我希望将所有映射逻辑合并到一个映射器中。时期。
我已经为公共属性定义了映射,但是当它变得有趣时,我在编译过程中得到了这个异常:
The return type ... is an abstract class or interface.
Provide a non abstract / non interface result type or a factory method.
Run Code Online (Sandbox Code Playgroud)
那么,我如何指定一个工厂方法,它基于特定属性的值或 pojo 的类,为我创建一个目标对象?我希望有一个能真正解决问题的好的代码片段。
谢谢!
是否可以在表达式中包含 if-else 或三元运算符之类的条件
@Mapping(expression="java(...)")
Run Code Online (Sandbox Code Playgroud)
我有一个返回 ArrayList 的最后一项的方法,但如果列表为空,它会返回 null。我需要一个条件,所以如果我收到该项目,我可以使用它,或者如果它为空,它将映射为空。
public static MyObjectDetail getLastOne(MyObject myObject) {
List<MyObjectDetail> details = myObject.getMyObjectDetails();
if(details.isEmpty()) {
return null;
} else {
return myObject.getLastDetail(myObject);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我当前使用的@Mapping,如果列表不为空,它就可以正常工作。
@Mapping(expression = "java(MyObjectDetailMapper.getLastOne(myObject).getNumber())", target = "number"),
Run Code Online (Sandbox Code Playgroud) 鉴于这个原型
option java_outer_classname = "FooProto";
message Foo {
string bar = 1;
}
Run Code Online (Sandbox Code Playgroud)
这个java类:
public class MyFoo {
String bar;
}
Run Code Online (Sandbox Code Playgroud)
这个映射器(使用 Mapstruct):
@Mapper
public interface FooMapper() {
FooProto.Foo toProtoFoo(MyFoo myFoo);
}
Run Code Online (Sandbox Code Playgroud)
当我有一个带有空栏的 MyFoo 实例并尝试将其映射到原型时,我得到一个 NullPointerException。
这是因为映射器自动生成的代码调用原型的自动生成方法,如下所示:
public Builder setBar(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bar_ = value;
onChanged();
return this;
}
Run Code Online (Sandbox Code Playgroud)
有什么办法可以避免这个问题吗?(这不涉及在映射之前清理 MyFoo 实例,使其没有空值)
mapstruct ×10
java ×7
mapping ×2
enums ×1
expression ×1
hibernate ×1
nested ×1
null ×1
spring-boot ×1