简体   繁体   English

休眠关系外键约束失败

[英]Hibernate relationship foreign key constraint fails

I've put together two basic classes/tables in order to learn how the use Hibernate. 为了了解如何使用Hibernate,我整理了两个基本的类/表。

Upon execution of the following code; 执行以下代码时;

Session hbSession = HibernateUtil.getSession();

        Showroom showroom = new Showroom();
        showroom.setLocation("London");
        showroom.setManager("John Doe");

        List<Car> cars = new ArrayList<Car>();
        cars.add(new Car("Vauxhall Astra", "White"));
        cars.add(new Car("Nissan Juke", "Red"));

        showroom.setCars(cars);

        hbSession.beginTransaction();
        hbSession.save(showroom);
        hbSession.getTransaction().commit();

I'm getting this error; 我收到此错误;

Cannot add or update a child row: a foreign key constraint fails (`ticket`.`Car`, CONSTRAINT `FK107B4D9254CE5` FOREIGN KEY (`showroomId`) REFERENCES `Showroom` (`id`))

I'm not really sure where it's going wrong. 我不太确定哪里出了问题。 Here are the two annotated classes; 这是两个带注释的类。

@Entity
public class Showroom {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @OneToMany
    @JoinColumn(name="showroomId")
    @Cascade(CascadeType.ALL)
    private List<Car> cars = null;

    private String manager = null;
    private String location = null;

    public int getId() {
        return id;
    }

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

    public List<Car> getCars() {
        return cars;
    }

    public void setCars(List<Car> cars) {
        this.cars = cars;
    }

    public String getManager() {
        return manager;
    }

    public void setManager(String manager) {
        this.manager = manager;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
}

@Entity
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    private String color;
    private int showroomId;

    public Car(String name, String color) {
        this.setName(name);
        this.setColor(color);
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getShowroomId() {
        return showroomId;
    }

    public void setShowroomId(int showroomId) {
        this.showroomId = showroomId;
    }
}

For the time being I've let Hibernate create the tables in the MySQL database. 目前,我已经让Hibernate在MySQL数据库中创建表。 I've checked and the relationship between the database does exist in the Car table. 我已经检查过,并且Car表中确实存在数据库之间的关系。

Is anyone able to tell my why this isn't working? 有谁能告诉我为什么这不起作用?

At a guess I'm saying it's because the showroom doesn't have an Id, as this is auto-generated by MySQL, so the cars cannot be saved? 我猜是因为陈列室没有Id,因为它是由MySQL自动生成的,所以无法保存汽车? Is that right? 那正确吗?

You have a couple problems here. 你这里有几个问题。 In Car, you have a field that is supposed to be a FK reference to the Showroom. 在Car中,您有一个字段,该字段应该是对Showroom的FK引用。 However, this is a native int. 但是,这是一个本地int。 That means that it has a value of zero. 这意味着它的值为零。 If your Car object should reference your Showroom, then you would have to add a reference with @ManyToOne 如果您的Car对象应引用您的Showroom,则必须使用@ManyToOne添加引用

@ManyToOne
@JoinColumn(name="showroomId")
private Showroom showroom;

Then your field in Showroom changes to 然后,您在Showroom中的字段更改为

@OneToMany(mappedBy = "showroom")
@Cascade(value = { org.hibernate.annotations.CascadeType.ALL } )
private List<Car> cars = null;

If you do this, you need to set the reference in Car explicitly. 如果这样做,则需要在Car中显式设置引用。 Either way, the showroomId (also a native int) needs to go. 无论哪种方式,都需要走ShowroomId(也是一个本地int)。 Either you shouldn't have the field in your Car object at all, and you have only the backref List, or you need to replace it with a properly mapped Entity reference (see above). 或者,您根本不应该在Car对象中包含该字段,而只有backref List,或者需要用正确映射的Entity引用替换它(请参见上文)。

The other problem is that your generated Column is a native type. 另一个问题是您生成的Column是本机类型。 This becomes a value of 0, and Hibernate will not automatically/correctly generate the value. 这将成为0值,并且Hibernate将不会自动/正确生成该值。

Change your primary key reference in both Entities (along with the getters and setters) 更改两个实体中的主键参考(以及getter和setter)

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public Integer getId() {
    return id;
}
public void setId(Integer id) {
    this.id = id;
}

In order to load the entities successfully from the DB, I also had to add a default constructor for Car. 为了从数据库成功加载实体,我还必须为Car添加默认的构造函数。

protected Car() {
}

Then your example will work. 然后您的示例将起作用。

I've managed to get this working. 我设法做到了这一点。 The first problem was that I didn't have a showroom property in my Car class. 第一个问题是我的汽车课上没有陈列室。 The second was the way I was saving the objects didn't seem to be correct. 第二个是我保存对象的方式似乎不正确。

I've altered my classes to this.. 我已经改变了班级。

@Entity
public class Showroom {

    @Id
    @GeneratedValue
    private int id;

    private String location;
    private String manager;

    @OneToMany(mappedBy="showroom")
    private List<Car> cars;

    public List<Car> getCars() {
        return cars;
    }

    public void setCars(List<Car> cars) {
        this.cars = cars;
    }
}

@Entity
public class Car {

    @Id
    @GeneratedValue
    private int Id;

    private String name;
    private String color;

    @ManyToOne
    @JoinColumn(name="showroomId")
    private Showroom showroom;

    public Car(String name, String color) {
        this.name = name;
        this.color = color;
    }
}

And the save functions are now; 现在保存功能;

Session hbSession = HibernateUtil.getSession();
        hbSession.beginTransaction();

        // Create a showroom
        Showroom showroom = new Showroom();
        showroom.setManager("John Doe");
        showroom.setLocation("London");
        hbSession.save(showroom);

        // Create car one, assign the showroom and save
        Car car1 = new Car("Vauxhall Astra", "White");
        car1.setShowroom(showroom);
        hbSession.save(car1);

        // Create car two, assign the showroom and save
        Car car2 = new Car("Nissan Juke", "Red");
        car2.setShowroom(showroom);
        hbSession.save(car2);

        hbSession.getTransaction().commit();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM