Hibernate вставляет неожиданную строкуJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Hibernate вставляет неожиданную строку

Сообщение Anonymous »

У меня есть схема, в которой есть таблица отчетов с заголовком, в каждом отчете есть набор клиентов, а у каждого клиента есть набор продуктов, два отношения «один-ко-многим».
Вещь Мои клиенты и первичный ключ продукта являются составными, как показано во фрагментах.
Мой объект заголовка:

Код: Выделить всё

@Entity
@Builder
@Getter
@NoArgsConstructor
@Table(name = "samples_report_header")
public class SamplesReportHeaderEntity implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;

@Column(name = "month", nullable = false)
private Integer month;

@Column(name = "year", nullable = false)
private Integer year;

@Column(name = "operator", nullable = false)
private String operator;

@Column(name = "printed_YN", nullable = false)
private Character printedYN;

// One-to-Many relationship with SamplesReportCustomer
@OneToMany(mappedBy = "reportHeader", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set customers = new HashSet();

public SamplesReportHeaderEntity(Long id, Integer month, Integer year, String operator, Character printedYN, Set customers) {
this.id = id;
this.month = month;
this.year = year;
this.operator = operator;
this.printedYN = printedYN;
this.customers = Objects.requireNonNullElseGet(customers, HashSet::new);
}

@Override
public int hashCode() {
return Objects.hash(id);
}

@Override
public String toString() {
return "HEADER: {" + this.id + "," + this.month + "," + this.year + "," + this.operator + "}";
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
SamplesReportHeaderEntity that = (SamplesReportHeaderEntity) o;
return id == that.id ;
}
}
мой клиент:

Код: Выделить всё

@Entity
@Builder
@Getter
@Setter
@NoArgsConstructor
@Table(name = "samples_report_customer")
public class SamplesReportCustomerEntity implements Serializable {

@EmbeddedId
private SamplesReportCustomerId id;

@Column(name = "bem_area")
private String bemArea;

@Column(name = "customer_name")
private String customerName;

@Column(name = "customer_address")
private String customerAddress;

@Column(name = "customer_type")
private String customerType;

@Column(name = "visit_feedback")
private String visitFeedback;

@Column(name = "visit_date")
private LocalDate visitDate;

@Column(name = "attachment")
private byte[] attachment;

@Column(name = "mime_type")
private String mimeType;

@Column(name = "total_penalty")
private BigDecimal totalPenalty;

@Column(name = "jumping_YN")
private Character jumpingYN;

@Column(name = "repeated_sales_YN")
private Character repeatedSalesYN;

@Column(name = "expensive_items_YN")
private Character expensiveItemsYN;

@Column(name = "normal_sales_YN")
private Character normalSalesYN;

@Column(name = "product_sales_YN")
private Character productSalesYN ;

@Column(name = "sales_quantity")
private Integer salesQuantity;

@Column(name = "sales_value")
private BigDecimal salesValue;

@Column(name = "bonus_quantity")
private Integer bonusQuantity;

@Column(name = "bonus_value")
private BigDecimal bonusValue;

// Many-to-One relationship with SamplesReportHeader
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("reportId")
@JoinColumn(name = "report_id", referencedColumnName = "id")
private SamplesReportHeaderEntity reportHeader;

@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set  products = new HashSet();;

public SamplesReportCustomerEntity(SamplesReportCustomerId id, String bemArea, String customerName, String customerAddress, String customerType, String visitFeedback, LocalDate visitDate, byte[] attachment,String mimeType, BigDecimal totalPenalty, Character jumpingYN, Character repeatedSalesYN, Character expensiveItemsYN,Character normalSalesYN ,Character productSalesYN,  Integer salesQuantity, BigDecimal salesValue, Integer bonusQuantity, BigDecimal bonusValue, SamplesReportHeaderEntity reportHeader, Set  products) {
this.id = id;
this.bemArea = bemArea;
this.customerName = customerName;
this.customerAddress = customerAddress;
this.customerType = customerType;
this.visitFeedback = visitFeedback;
this.visitDate = visitDate;
this.attachment = attachment;
this.mimeType = mimeType;
this.totalPenalty = totalPenalty;
this.jumpingYN = jumpingYN;
this.repeatedSalesYN = repeatedSalesYN;
this.expensiveItemsYN = expensiveItemsYN;
this.normalSalesYN = normalSalesYN ;
this.productSalesYN = productSalesYN;
this.salesQuantity = salesQuantity;
this.salesValue = salesValue;
this.bonusQuantity = bonusQuantity;
this.bonusValue = bonusValue;
if(reportHeader == null)
this.reportHeader = new SamplesReportHeaderEntity();
else
this.reportHeader = reportHeader;

if(products == null)
this.products = new HashSet();
else
this.products = products;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SamplesReportCustomerEntity that = (SamplesReportCustomerEntity) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}
}
мой идентификатор клиента:

Код: Выделить всё

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class SamplesReportCustomerId implements Serializable {

@NotNull
@Column(name = "GSK_customer_code", nullable = false)
private String GSKCustomerCode;

@NotNull
@Column(name = "report_id", nullable = false)
private Long reportId;

@NotNull
@Column(name = "distributor_customer_code", nullable = false)
private String distributorCustomerCode;

@NotNull
@Column(name = "distributor_code", nullable = false)
private String distributorCode;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SamplesReportCustomerId that = (SamplesReportCustomerId) o;
return Objects.equals(GSKCustomerCode, that.GSKCustomerCode) &&
Objects.equals(reportId, that.reportId) &&
Objects.equals(distributorCode,that.distributorCode) &&
Objects.equals(distributorCustomerCode,that.distributorCustomerCode);
}
@Override
public int hashCode() {
return Objects.hash(GSKCustomerCode, reportId , distributorCode , distributorCustomerCode);
}
}
моя сущность продукта:

Код: Выделить всё

@Entity
@Builder
@Data
@NoArgsConstructor
@Table(name = "samples_report_product")
public class SamplesReportProductEntity implements Serializable {

@EmbeddedId
private SamplesReportProductId id ;

@Column(name = "brand")
private String brand;

@Column(name = "item_description")
private String itemDescription;

@Column(name = "gsk_item_code")
private String GSKItemCode;

@Column(name = "sales_quantity")
private Integer salesQuantity;

@Column(name = "sales_value")
private BigDecimal salesValue;

@Column(name = "bonus_quantity")
private Integer bonusQuantity;

@Column(name = "bonus_value")
private BigDecimal bonusValue;

@Column(name = "visit_feedback")
private String visitFeedback;

@Column(name = "visit_date")
private LocalDate visitDate;

@Column(name = "penalty1")
private BigDecimal penalty1;

@Column(name = "penalty2")
private BigDecimal penalty2;

@Column(name = "penalty3")
private BigDecimal penalty3;

@Column(name = "total_penalty")
private BigDecimal totalPenalty;

@ManyToOne
@JoinColumns({
@JoinColumn(name = "GSK_customer_code", referencedColumnName = "GSK_customer_code",nullable = false,insertable = false,  updatable = false),
@JoinColumn(name = "report_id", referencedColumnName = "report_id", nullable = false,insertable = false, updatable = false) ,
@JoinColumn(name = "distributor_code", referencedColumnName = "distributor_code",nullable = false,insertable = false, updatable = false) ,
@JoinColumn(name = "distributor_customer_code", referencedColumnName = "distributor_customer_code",nullable = false,insertable = false, updatable = false)
})
private SamplesReportCustomerEntity customer;

public SamplesReportProductEntity(SamplesReportProductId id,String brand, String itemDescription, String GSKItemCode, Integer salesQuantity, BigDecimal salesValue, Integer bonusQuantity, BigDecimal bonusValue, String visitFeedback, LocalDate visitDate, BigDecimal penalty1, BigDecimal penalty2, BigDecimal penalty3, BigDecimal totalPenalty, SamplesReportCustomerEntity customer) {
this.id = id;
this.brand = brand;
this.itemDescription = itemDescription;
this.GSKItemCode = GSKItemCode;
this.salesQuantity = salesQuantity;
this.salesValue = salesValue;
this.bonusQuantity = bonusQuantity;
this.bonusValue = bonusValue;
this.visitFeedback = visitFeedback;
this.visitDate = visitDate;
this.penalty1 = penalty1;
this.penalty2 = penalty2;
this.penalty3 = penalty3;
this.totalPenalty = totalPenalty;
if(customer == null)
this.customer = new SamplesReportCustomerEntity();
else
this.customer = customer;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SamplesReportProductEntity that = (SamplesReportProductEntity) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hash(id);
}
}
Идентификатор моего продукта:

Код: Выделить всё

@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SamplesReportProductId implements Serializable {

@NotNull
@Column(name = "distributor_code", nullable = false)
private String distributorCode;

@NotNull
@Column(name = "distributor_customer_code", nullable = false)
private String distributorCustomerCode;

@NotNull
@Column(name = "distributor_invoice_id", nullable = false)
private String distributorInvoiceId;

@NotNull
@Column(name = "sales_type", nullable = false)
private String salesType;

@NotNull
@Column(name = "distributor_item_code", nullable = false)
private String distributorItemCode;

@NotNull
@Column(name = "batch_code", nullable = false)
private String batchCode;

@NotNull
@Column(name = "distributor_invoice_date", nullable = false)
private LocalDateTime distributorInvoiceDate;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SamplesReportProductId that = (SamplesReportProductId) o;
return Objects.equals(distributorCode, that.distributorCode) &&
Objects.equals(distributorCustomerCode, that.distributorCustomerCode) &&
Objects.equals(distributorInvoiceId, that.distributorInvoiceId) &&
Objects.equals(salesType, that.salesType) &&
Objects.equals(distributorItemCode, that.distributorItemCode) &&
Objects.equals(batchCode, that.batchCode) &&
Objects.equals(distributorInvoiceDate, that.distributorInvoiceDate);
}
@Override
public int hashCode() {
return Objects.hash(distributorCode, distributorCustomerCode, distributorInvoiceId, salesType, distributorItemCode, batchCode, distributorInvoiceDate);
}
}
Я пытаюсь заполнить эти таблицы из денормализованной таблицы истории, где я создаю объект отчета, добавляю клиента в его набор клиентов и добавляю продукт в набор продуктов клиента, что-то вроде этого :

Код: Выделить всё

for (var record :  bemHistoryEntities) {
String operator = record.getOperator();
String gskCustomerCode = record.getGskCustomerCode();
String distCustCode = record.getDistributorCustomerCode();
String distCode = record.getDistributorCode();

// getting the report header
List headersList = headerEntities.stream().filter(entity ->
(entity.getMonth() == month && entity.getYear() == year && operator.equals(entity.getOperator())))
.collect(Collectors.toList());
SamplesReportHeaderEntity headerEntity = null;

// header coming from the db
if (headersList.size() > 0) {
headerEntity = headersList.get(0);
} else {
// if not persisted before, create it
headerEntity = samplesReportHeaderRepository.save(new SamplesReportHeaderEntity().builder()
.operator(operator)
.month(month)
.year(year)
.printedYN('N')
.build());
headerEntities.add(headerEntity);
}

// creating samples customer from the record
SamplesReportCustomerEntity customer = new SamplesReportCustomerEntity().builder()
.id(new SamplesReportCustomerId(gskCustomerCode, headerEntity.getId(), distCustCode, distCode))
.bemArea(record.getBemArea())
.customerAddress(record.getDistributorCustomerAddress())
.customerName(record.getDistributorCustomerName())
.customerType(record.getBemCustomerType())
.jumpingYN(intermediateEntityMap.get(gskCustomerCode).getJumpingYN())
.repeatedSalesYN(intermediateEntityMap.get(gskCustomerCode).getRepeatedYN())
.expensiveItemsYN(intermediateEntityMap.get(gskCustomerCode).getExpensiveYN())
.productSalesYN(intermediateEntityMap.get(gskCustomerCode).getProductYN())
.normalSalesYN(intermediateEntityMap.get(gskCustomerCode).getNormalYN())
.build();

// creating samples product from the record to the created customer
SamplesReportProductEntity product = new SamplesReportProductEntity().builder()
.id(new SamplesReportProductId(distCode, distCustCode, record.getInvoiceNumber(), record.getSalesType(), record.getDistributorItemCode(), record.getBatchCode(), record.getInvoiceDate()))
.brand(record.getBrand())
.itemDescription(record.getGskItemDescription())
.GSKItemCode(record.getGskItemCode())
.build();

customer.getProducts().add(product);
headerEntity.getCustomers().add(customer);
}
Все в порядке, пока не начнется этап фиксации, он всегда пытается вставить строку в таблицу заголовков отчета, которую я никоим образом не создал, и даже если я напечатал содержимое контекста персистентности, это там тоже не было, и, конечно, это нарушает ненулевые ограничения, приводящие к сбою всей транзакции.

Детали: Неудачная строка содержит (70, null , ноль, ноль, null).

Код: Выделить всё

persistence context after the function execution:
Entity in context: HEADER: {67,10,2024,Hossam}
Entity in context: HEADER: {66,10,2024,Vacant}
Entity in context: HEADER: {69,10,2024,Samir}
Entity in context: HEADER: {68,10,2024,Saad}
Я отладил выполнение всей функции, но функция commitTransactionAfterReturning всегда выдает указанную выше ошибку.

Подробнее здесь: https://stackoverflow.com/questions/793 ... pected-row
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»