У меня ошибка при использовании составного первичного ключа в Hibernate, который говорит: Причина: java. sql .SQLIntegrityConstraintViolationException: Дублирующая запись 'PRO-0001' для ключа 'PRIMARY'
Но составной ключ, который я использую, уникален для конкретной таблицы.
Я новичок в hibernate и нашел здесь похожий вопрос Несмотря на наличие составного первичного ключа, Hibernate выдает ошибку, когда только один ключ уникален , но не может решить мою проблему.
Структура таблицы - Создано Hibernate
Product Entity
import com.google.common.base.Objects;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDate;
@Entity
@Table(name = "product")
public class Product implements Serializable {
@EmbeddedId
private ProductId productId;
@Column(name = "manufactured_date")
private LocalDate manufacturedDate;
@Column(name = "expiry_date")
private LocalDate expiryDate;
@Column(name = "available_quantity", nullable = false)
private double availableQuantity;
@Column(name = "reorder_level")
private double reorderLevel;
@Column(name = "buying_price", nullable = false)
private double buyingPrice;
@Column(name = "selling_price")
private double sellingPrice;
@Column(name = "remark")
private String remark;
@ManyToOne
@MapsId("product_id")
@JoinColumn(name = "product_id")
private Store store;
public Product() {
}
public Product(ProductId productId, LocalDate manufacturedDate, LocalDate expiryDate, double availableQuantity,
double reorderLevel, double buyingPrice, double sellingPrice, String remark, Store store) {
this.productId = productId;
this.manufacturedDate = manufacturedDate;
this.expiryDate = expiryDate;
this.availableQuantity = availableQuantity;
this.reorderLevel = reorderLevel;
this.buyingPrice = buyingPrice;
this.sellingPrice = sellingPrice;
this.remark = remark;
this.store = store;
}
// Getters and Setters
}
ProductId Embeddable Class
import com.google.common.base.Objects;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;
@Embeddable
public class ProductId implements Serializable {
@Column(name = "product_id")
private String productId;
@Column(name = "batch_code")
private String batchCode;
public ProductId() {
}
public ProductId(String productId, String batchCode) {
this.productId = productId;
this.batchCode = batchCode;
}
// getters and setters
// equals
// hashCode
}
Store Entity
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "store")
public class Store {
@Id
@Column(name = "product_id")
private String productId;
@Column(name = "description")
private String description;
@Column(name = "units")
private String units;
@OneToMany(mappedBy = "store", cascade = CascadeType.ALL)
private List<Product> products = new ArrayList<>();
public Store() {
}
public Store(String productId, String description, String units, List<Product> products) {
this.productId = productId;
this.description = description;
this.units = units;
this.products = products;
}
// getters and setters
}
Реализация
// Sample data
String productId = "PRO-0001";
String batchCode = "BAT-0002";
double quantity = 150;
double buyingPrice = 12;
double sellingPrice = 10;
double reOrderLevel = 500;
LocalDate manufacturedDate = LocalDate.of(2020, 04, 01);
LocalDate expiryDate = LocalDate.of(2020, 04, 30);
String description = "Product one";
// Save to database
Transaction transaction = null;
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
// start a transaction
transaction = session.beginTransaction();
// Create new store
Store store = new Store();
Product product = new Product();
ProductId productIdEntity = new ProductId();
productIdEntity.setBatchCode(batchCode);
productIdEntity.setProductId(productId);
// Product entity related
// store
product.setStore(store);
// productId
product.setProductId(productIdEntity);
// quantity
product.setAvailableQuantity(quantity);
// buyingPrice
product.setBuyingPrice(buyingPrice);
// reOrderLevel
product.setReorderLevel(reOrderLevel);
// sellingPrice
product.setSellingPrice(sellingPrice);
// manufacturedDate
product.setManufacturedDate(manufacturedDate);
// expiryDate
product.setExpiryDate(expiryDate);
// description
product.setRemark(description);
// Store entity related
// productId
store.setProductId(productId);
// Products
List<Product> inputProduct = new ArrayList<>();
inputProduct.add(product);
store.setProducts(inputProduct);
// save Store
session.save(store);
// commit transaction
transaction.commit();
} catch (Exception e) {
if (transaction != null) {
transaction.rollback();
}
e.printStackTrace();
}
Подробная ошибка
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1356)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:443)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3202)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2370)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at org.mdjee.stockmonitor.utils.Test.main(Test.java:80)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3235)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3760)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1352)
... 9 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'PRO-0001' for key 'PRIMARY'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1092)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1040)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1347)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1025)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 20 more