簡體   English   中英

帶有復合鍵的休眠一對多關系(SAVE操作)

[英]Hibernate One-Many relationship with Composite Key (SAVE Operation)

表格腳本:

DROP TABLE IF EXISTS STOCK; CREATE TABLE STOCK (   STOCK_ID INT(10) NOT NULL,   STOCK_CODE VARCHAR(10) NOT NULL,   STOCK_NAME VARCHAR(20) NOT NULL,   PRIMARY KEY (STOCK_ID,STOCK_CODE),   KEY STOCK_CODE_IDX (STOCK_CODE) ); 
DROP TABLE IF EXISTS STOCK_DAILY_RECORD; 

CREATE TABLE  STOCK_DAILY_RECORD (   RECORD_ID INT(10) NOT NULL,   STOCK_CODE VARCHAR(10) NOT NULL,   PRICE_OPEN FLOAT(6,2) DEFAULT NULL,   PRICE_CLOSE FLOAT(6,2) DEFAULT NULL,   PRICE_CHANGE FLOAT(6,2) DEFAULT NULL,   VOLUME BIGINT(20) DEFAULT NULL,   STOCK_ID INT(10) NOT NULL,   PRIMARY KEY (RECORD_ID,STOCK_CODE),   KEY FK_STOCK_ID (STOCK_ID,STOCK_CODE),   CONSTRAINT FK_STOCK_ID FOREIGN KEY (STOCK_ID,STOCK_CODE) REFERENCES STOCK (STOCK_ID,STOCK_CODE) ) ;

這是主類,在其中可以填充實體類以將值保存在stockstockdailyrecord表中:

package org.hibernate.HibernateEntity;

import org.hibernate.Session;

import com.model.Stock;
import com.model.StockDailyRecord;
import com.model.StockDailyRecordId;
import com.model.StockId;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main(String[] args) {
        System.out.println("Hibernate one to one (Annotation)");
        Session session = HibernateUtil.getSessionFactory().openSession();

        session.beginTransaction();

        Stock stock = new Stock();
        StockId id = new StockId(2, "7052");
        stock.setId(id);
        stock.setStockName("PADINI");

        StockDailyRecord stockDetail = new StockDailyRecord();
        StockDailyRecordId id1 = new StockDailyRecordId(101, "7052");
        stockDetail.setId(id1);
        stockDetail.setPriceChange(200.0f);
        stockDetail.setPriceClose(210.0f);
        stockDetail.setPriceOpen(120.0f);
        stockDetail.setVolume(12l);
        stock.getStockDailyRecords().add(stockDetail);
        stockDetail.setStock(stock);

        session.save(stock);
        //session.save(stockDetail);
        session.getTransaction().commit();
        System.out.println("Done");
    }
}

實體類別,該類別是由內嵌hibernate和id的復合鍵所配置:

package com.model;
// Generated Jan 12, 2018 8:17:38 AM by Hibernate Tools 5.2.6.Final

import java.util.HashSet;
import java.util.Set;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

/**
 * Stock generated by hbm2java
 */
@Entity
@Table(name = "stock", catalog = "testdb")
public class Stock implements java.io.Serializable {

    private StockId id;
    private String stockName;
    private Set<StockDailyRecord> stockDailyRecords = new HashSet<StockDailyRecord>(0);

    public Stock() {
    }

    public Stock(StockId id, String stockName) {
        this.id = id;
        this.stockName = stockName;
    }

    public Stock(StockId id, String stockName, Set<StockDailyRecord> stockDailyRecords) {
        this.id = id;
        this.stockName = stockName;
        this.stockDailyRecords = stockDailyRecords;
    }

    @EmbeddedId

    @AttributeOverrides({ @AttributeOverride(name = "stockId", column = @Column(name = "STOCK_ID", nullable = false)),
            @AttributeOverride(name = "stockCode", column = @Column(name = "STOCK_CODE", nullable = false, length = 10)) })
    public StockId getId() {
        return this.id;
    }

    public void setId(StockId id) {
        this.id = id;
    }

    @Column(name = "STOCK_NAME", nullable = false, length = 20)
    public String getStockName() {
        return this.stockName;
    }

    public void setStockName(String stockName) {
        this.stockName = stockName;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock")
    @Cascade(CascadeType.ALL)
    public Set<StockDailyRecord> getStockDailyRecords() {
        return this.stockDailyRecords;
    }

    public void setStockDailyRecords(Set<StockDailyRecord> stockDailyRecords) {
        this.stockDailyRecords = stockDailyRecords;
    }

}

實體類別,該類別是由內嵌hibernate和id的復合鍵所配置:

package com.model;
// Generated Jan 12, 2018 8:17:38 AM by Hibernate Tools 5.2.6.Final

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 * StockDailyRecord generated by hbm2java
 */
@Entity
@Table(name = "stock_daily_record", catalog = "testdb")
public class StockDailyRecord implements java.io.Serializable {

    private StockDailyRecordId id;
    private Stock stock;
    private Float priceOpen;
    private Float priceClose;
    private Float priceChange;
    private Long volume;

    public StockDailyRecord() {
    }

    public StockDailyRecord(StockDailyRecordId id, Stock stock) {
        this.id = id;
        this.stock = stock;
    }

    public StockDailyRecord(StockDailyRecordId id, Stock stock, Float priceOpen, Float priceClose, Float priceChange,
            Long volume) {
        this.id = id;
        this.stock = stock;
        this.priceOpen = priceOpen;
        this.priceClose = priceClose;
        this.priceChange = priceChange;
        this.volume = volume;
    }

    @EmbeddedId

    @AttributeOverrides({ @AttributeOverride(name = "recordId", column = @Column(name = "RECORD_ID", nullable = false)),
            @AttributeOverride(name = "stockCode", column = @Column(name = "STOCK_CODE", nullable = false, length = 10)) })
    public StockDailyRecordId getId() {
        return this.id;
    }

    public void setId(StockDailyRecordId id) {
        this.id = id;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "STOCK_ID", referencedColumnName = "STOCK_ID", nullable = false, insertable = false, updatable = false),
            @JoinColumn(name = "STOCK_CODE", referencedColumnName = "STOCK_CODE", nullable = false, insertable = false, updatable = false) })
    public Stock getStock() {
        return this.stock;
    }

    public void setStock(Stock stock) {
        this.stock = stock;
    }

    @Column(name = "PRICE_OPEN", precision = 6)
    public Float getPriceOpen() {
        return this.priceOpen;
    }

    public void setPriceOpen(Float priceOpen) {
        this.priceOpen = priceOpen;
    }

    @Column(name = "PRICE_CLOSE", precision = 6)
    public Float getPriceClose() {
        return this.priceClose;
    }

    public void setPriceClose(Float priceClose) {
        this.priceClose = priceClose;
    }

    @Column(name = "PRICE_CHANGE", precision = 6)
    public Float getPriceChange() {
        return this.priceChange;
    }

    public void setPriceChange(Float priceChange) {
        this.priceChange = priceChange;
    }

    @Column(name = "VOLUME")
    public Long getVolume() {
        return this.volume;
    }

    public void setVolume(Long volume) {
        this.volume = volume;
    }

}

實體類別,該類別是由內嵌hibernate和id的復合鍵所配置:

package com.model;
// Generated Jan 12, 2018 8:17:38 AM by Hibernate Tools 5.2.6.Final

import javax.persistence.Column;
import javax.persistence.Embeddable;

/**
 * StockDailyRecordId generated by hbm2java
 */
@Embeddable
public class StockDailyRecordId implements java.io.Serializable {

    private int recordId;
    private String stockCode;

    public StockDailyRecordId() {
    }

    public StockDailyRecordId(int recordId, String stockCode) {
        this.recordId = recordId;
        this.stockCode = stockCode;
    }

    @Column(name = "RECORD_ID", nullable = false)
    public int getRecordId() {
        return this.recordId;
    }

    public void setRecordId(int recordId) {
        this.recordId = recordId;
    }

    @Column(name = "STOCK_CODE", nullable = false, length = 10)
    public String getStockCode() {
        return this.stockCode;
    }

    public void setStockCode(String stockCode) {
        this.stockCode = stockCode;
    }

    public boolean equals(Object other) {
        if ((this == other))
            return true;
        if ((other == null))
            return false;
        if (!(other instanceof StockDailyRecordId))
            return false;
        StockDailyRecordId castOther = (StockDailyRecordId) other;

        return (this.getRecordId() == castOther.getRecordId())
                && ((this.getStockCode() == castOther.getStockCode()) || (this.getStockCode() != null
                        && castOther.getStockCode() != null && this.getStockCode().equals(castOther.getStockCode())));
    }

    public int hashCode() {
        int result = 17;

        result = 37 * result + this.getRecordId();
        result = 37 * result + (getStockCode() == null ? 0 : this.getStockCode().hashCode());
        return result;
    }

}

實體類別,該類別是由內嵌hibernate和id的復合鍵所配置:

package com.model;
// Generated Jan 12, 2018 8:17:38 AM by Hibernate Tools 5.2.6.Final

import javax.persistence.Column;
import javax.persistence.Embeddable;

/**
 * StockId generated by hbm2java
 */
@Embeddable
public class StockId implements java.io.Serializable {

    private int stockId;
    private String stockCode;

    public StockId() {
    }

    public StockId(int stockId, String stockCode) {
        this.stockId = stockId;
        this.stockCode = stockCode;
    }

    @Column(name = "STOCK_ID", nullable = false)
    public int getStockId() {
        return this.stockId;
    }

    public void setStockId(int stockId) {
        this.stockId = stockId;
    }

    @Column(name = "STOCK_CODE", nullable = false, length = 10)
    public String getStockCode() {
        return this.stockCode;
    }

    public void setStockCode(String stockCode) {
        this.stockCode = stockCode;
    }

    public boolean equals(Object other) {
        if ((this == other))
            return true;
        if ((other == null))
            return false;
        if (!(other instanceof StockId))
            return false;
        StockId castOther = (StockId) other;

        return (this.getStockId() == castOther.getStockId())
                && ((this.getStockCode() == castOther.getStockCode()) || (this.getStockCode() != null
                        && castOther.getStockCode() != null && this.getStockCode().equals(castOther.getStockCode())));
    }

    public int hashCode() {
        int result = 17;

        result = 37 * result + this.getStockId();
        result = 37 * result + (getStockCode() == null ? 0 : this.getStockCode().hashCode());
        return result;
    }

}

用於使用休眠配置創建會話工廠的類:

package org.hibernate.HibernateEntity;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        // Close caches and connection pools
        getSessionFactory().close();
    }

}

Stockdailyrecord 未填充庫存ID,請告知。

        08:20:05.202 [main] DEBUG org.hibernate.pretty.Printer - listing entities:
        08:20:05.203 [main] DEBUG org.hibernate.pretty.Printer - com.model.StockDailyRecord{priceChange=200.0, volume=12, priceClose=210.0, priceOpen=120.0, id=component[recordId,stockCode]{recordId=101, stockCode=7052}, stock=com.model.Stock#component[stockCode,stockId]{stockId=2, stockCode=7052}}
        08:20:05.203 [main] DEBUG org.hibernate.pretty.Printer - com.model.Stock{stockName=PADINI, stockDailyRecords=[com.model.StockDailyRecord#component[recordId,stockCode]{recordId=101, stockCode=7052}], id=component[stockCode,stockId]{stockId=2, stockCode=7052}}
        08:20:05.205 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
        08:20:05.206 [main] DEBUG org.hibernate.SQL - insert into testdb.stock (STOCK_NAME, STOCK_CODE, STOCK_ID) values (?, ?, ?)
        08:20:05.207 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1
        08:20:05.271 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
        08:20:05.271 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
        08:20:05.271 [main] DEBUG org.hibernate.SQL - insert into testdb.stock_daily_record (PRICE_CHANGE, PRICE_CLOSE, PRICE_OPEN, VOLUME, RECORD_ID, STOCK_CODE) values (?, ?, ?, ?, ?, ?)
        08:20:05.277 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1
        08:20:05.300 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
        08:20:05.315 [main] DEBUG o.h.util.JDBCExceptionReporter - Could not execute JDBC batch update [insert into testdb.stock_daily_record (PRICE_CHANGE, PRICE_CLOSE, PRICE_OPEN, VOLUME, RECORD_ID, STOCK_CODE) values (?, ?, ?, ?, ?, ?)]
        java.sql.BatchUpdateException: Field 'STOCK_ID' doesn't have a default value
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2024) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449) ~[mysql-connector-java-5.1.15.jar:na]
            at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) ~[hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) ~[hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268) [hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184) [hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) [hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) [hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216) [hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383) [hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133) [hibernate-core-3.6.3.Final.jar:3.6.3.Final]
            at org.hibernate.HibernateEntity.App.main(App.java:40) [classes/:na]
        Caused by: java.sql.SQLException: Field 'STOCK_ID' doesn't have a default value
            at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3603) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3535) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1989) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2150) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2626) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415) ~[mysql-connector-java-5.1.15.jar:na]
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1976) ~[mysql-connector-java-5.1.15.jar:na]
            ... 11 common frames omitted
        08:20:05.316 [main] WARN  o.h.util.JDBCExceptionReporter - SQL Error: 1364, SQLState: HY000
        08:20:05.316 [main] ERROR o.h.util.JDBCExceptionReporter - Field 'STOCK_ID' doesn't have a default value
        Exception in thread "main" org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
            at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
            at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
            at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
            at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
            at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
            at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
            at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
            at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
            at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
            at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
            at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
            at org.hibernate.HibernateEntity.App.main(App.java:40)
        Caused by: java.sql.BatchUpdateException: Field 'STOCK_ID' doesn't have a default value
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2024)
            at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449)
            at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
            at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
            ... 8 more
        Caused by: java.sql.SQLException: Field 'STOCK_ID' doesn't have a default value
            at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3603)
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3535)
            at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1989)
            at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2150)
            at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2626)
            at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
            at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415)
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1976)
            ... 11 more

由於未填寫字段STOCK_ID,但在數據庫中不能為空,因此引發了此錯誤。 在表STOCK的字段STOCK_ID的定義中添加子句AUTO_INCREMENT:

STOCK_ID INT(10) NOT NULL AUTO_INCREMENT

並返回到表STOCK_DAILY_RECORD中的RECORD_ID:

RECORD_ID INT(10) NOT NULL AUTO_INCREMENT

但是請記住,STOCK_CODE也不為空,您必須在插入之前將其填充。

您可以將代碼發布到創建實體實例並保存的位置嗎? 該錯誤不言自明。 您必須設置STOCK_ID的值。 您是否希望它是一個標識列(在mysql中為auto_increment)? 如果是這種情況,請更改數據模型以將STOCK_ID聲明為標識,並為stockId添加@GeneratedValue(strategy = GenerationType.IDENTITY)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM