为什么这种休眠关系不起作用?

时间:2019-06-30 18:57:11

标签: java hibernate

我尝试以n:m关系连接披萨和配料,而所有披萨都将配料作为配料的属性列表。但是在Relationstable中,当我创建一个新的Pizza并尝试提交时,Relationtable中的PizzaID出现错误。

关系表:

CREATE TABLE `Pizza_Ingredience_Relation` (
  `PizzaID` int(11) NOT NULL,
  `IngredientID` int(11) NOT NULL,
  `Amount` int(11) NOT NULL,
  `Volume_Unit` varchar(1) NOT NULL,
  PRIMARY KEY (`PizzaID`,`IngredientID`),
  KEY `FKc58en2gx5a8n1swmu9tda345` (`IngredientID`),
  CONSTRAINT `FK_IngredienceId` FOREIGN KEY (`IngredientID`) REFERENCES `Zutatenliste` (`ID`),
  CONSTRAINT `FKc58en2gx5a8n1swmu9tda345` FOREIGN KEY (`IngredientID`) REFERENCES `Zutatenliste` (`ID`),
  CONSTRAINT `FKhghfxg8raskdydyu8o8msxtfn` FOREIGN KEY (`PizzaID`) REFERENCES `Pizza` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

成分表:

CREATE TABLE `Zutatenliste` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` varchar(20) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

披萨桌:

CREATE TABLE `Pizza` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` varchar(20) NOT NULL,
  `PreisKlein` double NOT NULL,
  `PreisMittel` double NOT NULL,
  `PreisGroß` double NOT NULL,
  `PreisFamilie` double NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `ID` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

我有两个冬眠实体,一个是披萨实体,另一个是成分实体:


package Model.PizzenDB.SQLConnectionClasses.MySQL;

import Model.PizzenDB.Pizza;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.Where;

import javax.persistence.*;
import java.util.LinkedList;
import java.util.Set;

@Entity
@Table(name = "Pizza")
public class MySQLPizzaHibernateEntity {
    @Id
    @Column(name = "ID")
    private int id;
    @Column(name = "Name")
    private String name;
    @Column(name = "PreisKlein")
    private double smallPrice;
    @Column(name = "PreisMittel")
    private double middlePrice;
    @Column(name = "PreisGroß")
    private double bigPrice;
    @Column(name = "PreisFamilie")
    private double familyPrice;
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
            name = "Pizza_Ingredience_Relation",
            joinColumns = { @JoinColumn(name = "PizzaID",          referencedColumnName = "ID") },
            inverseJoinColumns = { @JoinColumn(name = "IngredientID") }
    )
    private Set<MySQLIngredientWithAmountHibernateEntity> ingredience;

    public MySQLPizzaHibernateEntity(String name, double smallPrice,            double middlePrice, double bigPrice, double familyPrice) {
        this.name = name;
        this.smallPrice = smallPrice;
        this.middlePrice = middlePrice;
        this.bigPrice = bigPrice;
        this.familyPrice = familyPrice;
    }

    public MySQLPizzaHibernateEntity() {
    }



}

@Entity
@Table(name = "Zutatenliste")
@SecondaryTable(name = "Pizza_Ingredience_Relation", pkJoinColumns = @PrimaryKeyJoinColumn(name = "IngredientID", referencedColumnName = "ID"))
public class MySQLIngredientWithAmountHibernateEntity {

    @Id
    @Column(name = "ID")
    private int id;
    @Column(name = "Name")
    private String name;
    @Column(table = "Pizza_Ingredience_Relation", name="Amount")
    private int amount;
    @Column(table = "Pizza_Ingredience_Relation", name = "Volume_Unit")
    private char unit;

    public MySQLIngredientWithAmountHibernateEntity(String name) {
        this.name = name;
    }

    public MySQLIngredientWithAmountHibernateEntity() {
        this("");
    }
}

我收到以下错误消息:

20:41:45 [main] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] ERROR - Field 'PizzaID' doesn't have a default value
20:41:45 [main] [org.hibernate.internal.ExceptionMapperStandardImpl] ERROR - HHH000346: Error during managed flush [org.hibernate.exception.GenericJDBCException: could not execute statement]

我不确定具体问题出在哪里,我想这与PizzaID外键有关,并且设置不正确。

2 个答案:

答案 0 :(得分:1)

对于多对多关系,您正在使用带有额外列的中间表,并且需要Embeddable键来构成由Pizza和Ingredient对象(名称缩写)组成的键。像这样:

@Embeddable
public class PizzaIngredientPk {
    private MySQLPizzaHibernateEntity pizza;
    private MySQLIngredientWithAmountHibernateEntity ingredient;

    @ManyToOne
    public MySQLPizzaHibernateEntity getPizza() {
        return pizza;
    }
    public void setPizza(MySQLPizzaHibernateEntity pizza) {
        this.pizza = pizza;
    }

    @ManyToOne
    public MySQLIngredientWithAmountHibernateEntity getIngredient() {
        return ingredient;
    }
    public void setIngredientID(MySQLIngredientWithAmountHibernateEntity ingredient) {
        this.ingredient = ingredient;
    }
}

然后它将作为MySQLIngredientWithAmountHibernateEntity中的嵌入式密钥

    @EmbeddedId
    PizzaIngredientPk pk = new PizzaIngredientPk();

但是这不适用于用于一对一关系的Secondarytable。 @SecondaryTable要求映射必须使用主键,但是在这种情况下,嵌入式ID将成为PK。实际上,您的设计存在缺陷。您正在尝试使多对多关系中的一侧一对一。

根据JPA文档,使用EmbeddedId注释时,必须只有一个EmbeddedId注释,而没有Id注释。

答案 1 :(得分:0)

尝试指定为休眠时自动产生主键。将此注释放在ID字段上方,然后重新创建数据库。

@GeneratedValue(strategy = GenerationType.IDENTITY)

请参阅:https://thoughts-on-java.org/hibernate-tips-use-auto-incremented-column-primary-key/