Составной первичный ключ, Hibernate выдает ошибку, когда только один ключ уникален - PullRequest
0 голосов
/ 24 апреля 2020

У меня ошибка при использовании составного первичного ключа в Hibernate, который говорит: Причина: java. sql .SQLIntegrityConstraintViolationException: Дублирующая запись 'PRO-0001' для ключа 'PRIMARY'

Но составной ключ, который я использую, уникален для конкретной таблицы.

Я новичок в hibernate и нашел здесь похожий вопрос Несмотря на наличие составного первичного ключа, Hibernate выдает ошибку, когда только один ключ уникален , но не может решить мою проблему.

Структура таблицы - Создано Hibernate

product table

store table

table relationship

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
...