【问题标题】:Model mapper Converter failed to convert Object to java.lang.Integer with java.lang.NullPointerException模型映射器转换器无法使用 java.lang.NullPointerException 将 Object 转换为 java.lang.Integer
【发布时间】:2022-08-02 15:30:11
【问题描述】:

也许有人可以给我一个insite。好的,我有带有嵌套事务集的购买实体。我试图做的是使用自定义方法转换额外的 DTO 属性 Integer paymentStatus 但为 ModelMapper Converter 获取 NullPointerException

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = \"purchase\")
public class Purchase {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = \"purchase_id\", nullable = false)
    private Integer purchaseId;

    @Column(name = \"purchase_total_cost\")
    private Double purchaseTotalCost;

    @Column(name = \"purchase_company_id\", nullable = false)
    private Integer purchaseCompanyId;

    @Column(name = \"purchase_user_id\", nullable = false)
    private Integer purchaseUserId;

    @Column(name = \"purchase_stock_id\", nullable = false)
    private Integer purchaseStockId;

    @Column(name = \"purchase_supplier_contact_id\")
    private Integer purchaseSupplierContactId;

    @Column(name = \"purchase_supplier_id\")
    private Integer purchaseSupplierId;

    @Column(name = \"purchase_inventory_id\")
    private Integer purchaseInventoryId;

    @Column(name = \"purchase_date\")
    private LocalDateTime purchaseDate;

    @Column(name = \"date_created\")
    @CreationTimestamp
    public LocalDateTime dateCreated;

    @Column(name = \"date_updated\")
    @UpdateTimestamp
    public LocalDateTime dateUpdated;


    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne
    @JoinColumn(name = \"purchase_user_id\", referencedColumnName = \"user_id\", insertable = false, updatable = false)
    private User purchaseUser;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne
    @JoinColumn(name = \"purchase_stock_id\", referencedColumnName = \"stock_id\", insertable = false, updatable = false)
    private Stock purchaseStock;


    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne
    @JoinColumn(name = \"purchase_supplier_id\", referencedColumnName = \"supplier_id\", insertable = false, updatable = false)
    private Supplier purchaseSupplier;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = \"purchase_supplier_contact_id\", referencedColumnName = \"contact_id\", insertable = false, updatable = false)
    private SupplierContact purchaseSupplierContact;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne
    @JoinColumn(name = \"purchase_company_id\", referencedColumnName = \"company_id\", insertable = false, updatable = false)
    private Company purchaseCompany;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @ManyToOne
    @JoinColumn(name = \"purchase_inventory_id\", referencedColumnName = \"inventory_id\", insertable = false, updatable = false)
    private Inventory purchaseInventory;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @OneToMany(fetch = FetchType.LAZY,
            mappedBy = \"costLogPurchase\")
    @Cascade({org.hibernate.annotations.CascadeType.MERGE,
            org.hibernate.annotations.CascadeType.DELETE,
            org.hibernate.annotations.CascadeType.REMOVE
    })
    private Set<CostLog> purchaseCostLogs;

    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @OneToMany(fetch = FetchType.LAZY,
            cascade = CascadeType.ALL,
            mappedBy = \"ingredientPurchase\")
    private Set<PurchaseHasIngredient> purchaseIngredients;

//    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    @OneToMany(fetch = FetchType.EAGER,
            cascade = CascadeType.ALL,
            mappedBy = \"transactionPurchase\")
    private Set<Transaction> purchaseTransactions;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = \"transaction\")
public class Transaction {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = \"transaction_id\", nullable = false)
    private Integer transactionId;

    @Column(name = \"transaction_status\")
    private Byte transactionStatus;

    @Column(name = \"transaction_amount\", nullable = false)
    private Double transactionAmount;

    @Column(name = \"transaction_code\", length = 100)
    private String transactionCode;

    @Column(name = \"transaction_payment_point_id\")
    private Integer transactionPaymentPointId;

    @Column(name = \"transaction_user_id\")
    private Integer transactionUserId;

    @Column(name = \"transaction_order_id\")
    private Integer transactionOrderId;

    @Column(name = \"transaction_purchase_id\")
    private Integer transactionPurchaseId;

    @Column(name = \"transaction_date\")
    public LocalDateTime transactionDate;

    @Column(name = \"date_created\")
    @CreationTimestamp
    public LocalDateTime dateCreated;

    @Column(name = \"date_updated\")
    @UpdateTimestamp
    public LocalDateTime dateUpdated;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = \"transaction_payment_point_id\", referencedColumnName = \"payment_point_id\", insertable = false, updatable = false)
    private PaymentPoint transactionPaymentPoint;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne
    @JoinColumn(name = \"transaction_user_id\", referencedColumnName = \"user_id\", insertable = false, updatable = false)
    private User transactionUser;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne
    @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    @JoinColumn(name = \"transaction_order_id\", referencedColumnName = \"order_id\", insertable = false, updatable = false)
    private Order transactionOrder;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    @ManyToOne(fetch = FetchType.EAGER)
    @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    @JoinColumn(name = \"transaction_purchase_id\", referencedColumnName = \"purchase_id\", insertable = false, updatable = false)
    private Purchase transactionPurchase;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TransactionDTO implements Serializable {
    private static final long serialVersionUID = 1L;

    private Integer transactionId;
    private Byte transactionStatus;
    private Double transactionAmount;
    private String transactionCode;
    private Integer transactionPaymentPointId;
    private String transactionPaymentPointName;
    private Integer transactionUserId;
    private String transactionUserName;
    private Integer transactionOrderId;
    private Integer transactionPurchaseId;
    public LocalDateTime transactionDate;
    public LocalDateTime dateCreated;
    public LocalDateTime dateUpdated;

}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PurchaseDTO {
    private static final long serialVersionUID = 1L;
    private Integer purchaseId;
    private Integer purchaseUserId;
    private String purchaseUserName;
    private Integer purchaseCompanyId;
    private Integer purchaseStockId;
    private String purchaseStockName;
    private Integer purchaseSupplierId;
    private String purchaseSupplierName;
    private Integer paymentStatus;               // this is additional property
    private Integer purchaseInventoryId;
    private Double purchaseTotalCost;
    private Integer purchaseSupplierContactId;
    private LocalDateTime purchaseDate;
    private LocalDateTime dateCreated;
    private LocalDateTime dateUpdated;

    private Set<PurchaseHasIngredientDTO> purchaseIngredients;
    private Set<TransactionDTO> purchaseTransactions;
@Configuration
public class ModelMapperConfig {

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setPreferNestedProperties(false)
                .setSkipNullEnabled(true)
                .setMatchingStrategy(MatchingStrategies.STANDARD);
        mapper.createTypeMap(Purchase.class, PurchaseDTO.class)
                .addMappings(purchaseDTOPropertyMapUsingPaymentStatusConverter);
       return mapper;
    }

    PropertyMap<Purchase, PurchaseDTO> purchaseDTOPropertyMapUsingPaymentStatusConverter = new PropertyMap<>() {
        @Override
        protected void configure() {
            using(ctx->mapSpecificFields(source.getPurchaseTransactions(), source.getPurchaseTotalCost())).
            map(source, destination.getPaymentStatus());

        }
    };
public Integer mapSpecificFields(Set<Transaction> set, Double total) {
        int b;
        if(set==null){
            b = 0;
        }
        double result = 0;
        for(Transaction transaction: set) {
            double sum = transaction.getTransactionAmount();
            sum++;
            result = sum/total;
        }
        if(result==0){
            b=0;
        }else if (result==1){
            b=2;
        }else{
            b=1;
        }
        return b;
    }
}
@Service
public class PurchaseService extends EntityMapperService<PurchaseDTO, Purchase> implements EntityService<Purchase> {

    @PersistenceContext
    private EntityManager entityManager;

    private final PurchaseRepository repository;
    private final PurchaseHasIngredientRepository purchaseIngredientsRepository;
    private final ModelMapper mapper;

 @Override
    public PurchaseDTO toDto(Purchase entity) {
        return Objects.isNull(entity)
                ? null
                : mapper.map(entity, PurchaseDTO.class);
    }
}

测试设置

@SpringBootTest
class PurchaseServiceTest {

    @Autowired
    private ModelMapper mapper;
    @Autowired
    private PurchaseService service;
    Transaction t1;
    Transaction t2;
    Set<Transaction> transactions;
    TransactionDTO td1;
    TransactionDTO td2;
    Set<TransactionDTO> transactionDTOS;
    Purchase purchase;
    PurchaseDTO dto;


    @BeforeEach
    void setUp() {
         t1 = Transaction.builder()
                .transactionId(11)
                .transactionAmount(12.00)
                .transactionPurchaseId(1)
                .build();
         t2 = Transaction.builder()
                .transactionId(12)
                .transactionAmount(10.00)
                .transactionPurchaseId(1)
                .build();

         transactions = Sets.newHashSet(t1,t2);

         td1 = TransactionDTO.builder()
                 .transactionPurchaseId(1)
                 .transactionId(11)
                 .transactionAmount(12.00)
                .build();

         td2 = TransactionDTO.builder()
                 .transactionId(12)
                 .transactionPurchaseId(1)
                 .transactionAmount(10.00)
                .build();

         transactionDTOS = Sets.newHashSet(td1,td2);

         purchase = Purchase.builder()
                .purchaseId(1)
                .purchaseCompanyId(2)
                .purchaseUserId(3)
                .purchaseStockId(4)
                .purchaseTransactions(transactions)
                .purchaseTotalCost(22.00)
                .build();

         dto = PurchaseDTO.builder()
                .purchaseId(1)
                .purchaseUserId(3)
                .purchaseCompanyId(2)
                .purchaseStockId(4)
                .paymentStatus(0)
                .purchaseTotalCost(22.00)
                 .purchaseTransactions(transactionDTOS)
                .build();

    }

    @DisplayName(\"JUnit test for toDto method for <Purchase, PurchaseDTO> typemap using paymentStatus converter\")
    @Test
    void toDtoUsingConverterForPurchaseTypeMap() {
        PurchaseDTO testedDto = service.toDto(purchase);
        assertThat(testedDto).isEqualTo(dto);

    }
}

堆栈跟踪错误

org.modelmapper.MappingException: ModelMapper mapping errors:

1) Converter com.hrc.hrcweb.ModelMapperConfig$1$$Lambda$1240/0x00000008013e8ea0@5f5efbfc failed to convert com.hrc.hrcweb.entities.Purchase to java.lang.Integer.

1 error

    at org.modelmapper.internal.Errors.throwMappingExceptionIfErrorsExist(Errors.java:380)
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:80)
    at org.modelmapper.ModelMapper.mapInternal(ModelMapper.java:573)
    at org.modelmapper.ModelMapper.map(ModelMapper.java:406)
    at com.hrc.hrcweb.servises.PurchaseService.toDto(PurchaseService.java:139)
    at com.hrc.hrcweb.servises.PurchaseService$$FastClassBySpringCGLIB$$ffc82405.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386)
    at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:85)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704)
    at com.hrc.hrcweb.servises.PurchaseService$$EnhancerBySpringCGLIB$$485f630d.toDto(<generated>)
    at com.hrc.hrcweb.servises.PurchaseServiceTest.toDtoUsingConverterForPurchaseTypeMap(PurchaseServiceTest.java:93)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: java.lang.NullPointerException: Cannot invoke \"com.hrc.hrcweb.entities.Purchase.getPurchaseTransactions()\" because \"this.source\" is null
    at com.hrc.hrcweb.ModelMapperConfig$1.lambda$configure$0(ModelMapperConfig.java:68)
    at org.modelmapper.internal.MappingEngineImpl.convert(MappingEngineImpl.java:306)
    at org.modelmapper.internal.MappingEngineImpl.setDestinationValue(MappingEngineImpl.java:243)
    at org.modelmapper.internal.MappingEngineImpl.propertyMap(MappingEngineImpl.java:187)
    at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:151)
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:105)
    at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:71)
    ... 77 more

我究竟做错了什么?

    标签: spring-boot dto modelmapper


    【解决方案1】:

    几个小时后,我找不到任何解决方案来映射其他属性或映射一些表达式以使用 DTO 对象属性执行一些自定义计算模型映射器,我不得不切换到地图结构对于这些操作,它有一些很好的自定义目标属性到表达式=java(anymethod)的映射,你可以使用任何方法来映射目标,非常方便。 example 也许有人会发现这些信息很有用。

    我用这段代码解决了所有问题

     @Mapping(target = "paymentStatus", expression = "java(getPaymentStatus(purchase))")
    PurchaseDTO toDto(Purchase purchase);
    

    这个自定义方法计算状态

    default Integer getPaymentStatus(Purchase purchase){
        Integer status;
        if(purchase.getPurchaseTransactions()==null){
            status = 0;
        }
        double result = 0;
        double sum = 0;
        double total = purchase.getPurchaseTotalCost();
        for(Transaction transaction: purchase.getPurchaseTransactions()) {
            sum += transaction.getTransactionAmount();
            result = sum/total;
        }
        if(result==0){
            status=0;
        }else if (result==1){
            status=2;
        }else{
            status=1;
        }
        return status;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-01
      • 2015-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-13
      相关资源
      最近更新 更多