首页 > 解决方案 > 通过实体图加载元素集合时,SqlNode 的文本没有引用预期的列数错误

问题描述

我有一个发票实体,其中包括帐单、送货地址、客户等,还保存付款和发票行项目。我正在使用命名实体图为我定义的每个自定义存储库方法加载不同的关联。

发票类

@Slf4j
@Entity
@Setter
@Getter
@ToString
@NoArgsConstructor
@Where(clause = "DELETED = 0")
@Relation(collectionRelation = "invoices")
@Table(indexes = { @Index(name = "place_of_supply_index", columnList = "placeOfSupply", unique = false),
    @Index(name = "invoice_date_index", columnList = "invoiceDate", unique = false),
    @Index(name = "due_date_index", columnList = "dueDate", unique = false),
    @Index(name = "payment_terms_index", columnList = "paymentTerms", unique = false) })
@NamedEntityGraphs({
    @NamedEntityGraph(name = "invoice_customer_details", attributeNodes = { @NamedAttributeNode("customer") }),
    @NamedEntityGraph(name = "invoice_details", attributeNodes = { @NamedAttributeNode("customer"),
        @NamedAttributeNode("billedTo"), @NamedAttributeNode("shippedTo") }),
    @NamedEntityGraph(name = "invoice_billing_details", attributeNodes = { @NamedAttributeNode("lineItems"),
        @NamedAttributeNode("payments") }),
    @NamedEntityGraph(name = "invoice_all_details", attributeNodes = { @NamedAttributeNode("customer"),
        @NamedAttributeNode("billedTo"), @NamedAttributeNode("shippedTo"), @NamedAttributeNode("lineItems"),
        @NamedAttributeNode("payments") }), })
public class Invoice extends AuditableEntity implements Identifiable<Long>, Serializable {

  private static final long serialVersionUID = 1560474818107754225L;

  @NotEmpty(message = "Cannot save invoice without Invoice Number")
  //@NaturalId
  @Column(unique = true, length = 20, nullable = false, updatable = false)
  private String invoiceNumber;

  @JsonIgnore
  private Integer deleted = 0;

  @NotEmpty(message = "Cannot save invoice without Line Items")
  @ElementCollection(fetch = FetchType.LAZY)
  @CollectionTable(name = "invoice_line_items", joinColumns = @JoinColumn(name = "invoice_id"))
  @JsonInclude(value = Include.NON_EMPTY, content = Include.NON_NULL)
  @OrderBy("serialNumber ASC")
  private Set<LineItem> lineItems;

  @ElementCollection(fetch = FetchType.LAZY)
  @CollectionTable(name = "invoice_payments", joinColumns = @JoinColumn(name = "invoice_id"))
  @JsonInclude(value = Include.NON_EMPTY, content = Include.NON_NULL)
  @OrderBy("paymentDate DESC")
  private Set<Payment> payments;

在存储库类中,我定义了一个方法来查找给定客户的所有已付款发票,并使用要加载的实体图PaymentsLineItems

  @Lock(LockModeType.OPTIMISTIC)
  @EntityGraph(value = "invoice_billing_details", type = EntityGraphType.LOAD)
  Page<Invoice> findByPaymentsIsNotNullAndCustomer_Id(Long id, Pageable pageable);

此方法抛出异常

org.springframework.orm.jpa.JpaSystemException: SqlNode's text did not reference expected number of columns; nested exception is org.hibernate.HibernateException: SqlNode's text did not reference expected number of columns
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:312)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy149.findByPaymentsIsNotNullAndCustomer_Id(Unknown Source)

我不知道如何解决这个问题。这是由于错误而失败的测试

@Test
  public void testFindAllPaidInvoicesByCustomer() throws Exception {
    //other invoice fields are set in the @Before annotated setup method
    invoice.setDueDate(Date.from(LocalDate.now().minusDays(10).atStartOfDay(ZoneId.of("Asia/Kolkata")).toInstant()));
    invoice.setPaymentTerms("NET-30");
    invoice
        .setInvoiceDate(Date.from(LocalDate.now().minusDays(40).atStartOfDay(ZoneId.of("Asia/Kolkata")).toInstant()));
    Set<Payment> payments = new HashSet<>();
    payments.add(getPayment());
    invoice.setPayments(payments);
    invoice.setLineItems(builder.getInvoiceObjectWithLineItems().getLineItems());
    Invoice savedInvoice = invoiceRepository.saveAndFlush(invoice);
    em.clear();
    Page<Invoice> invoices = invoiceRepository.findByPaymentsIsNotNullAndCustomer_Id(savedInvoice.getCustomer().getId(),
        PageRequest.of(0, 10));
    assertThat(invoices).isNotEmpty();
    assertThat((new ArrayList<>(invoices.getContent())).get(0).getId()).isEqualTo(savedInvoice.getId());
  }

标签: javahibernatespring-bootjpaspring-data-jpa

解决方案


错误是由于private Integer deleted = 0;

添加了列映射并解决了它。

  @JsonIgnore
  @Column(nullable = false)
  @ColumnDefault("0")
  private Integer deleted = 0;

推荐阅读