休眠关系外键约束失败
我已经把两个基本的类/表放在一起,以了解如何使用Hibernate。休眠关系外键约束失败
一旦执行下面的代码;
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();
我得到这个错误;
Cannot add or update a child row: a foreign key constraint fails (`ticket`.`Car`, CONSTRAINT `FK107B4D9254CE5` FOREIGN KEY (`showroomId`) REFERENCES `Showroom` (`id`))
我不太确定它出错的地方。这里是两个带注释的类;
@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;
}
}
暂时我让Hibernate在MySQL数据库中创建表。我已经检查过并且数据库之间的关系确实存在于Car表中。
有人能告诉我为什么这不起作用吗?
我猜这是因为陈列室没有Id,因为这是由MySQL自动生成的,所以汽车无法保存?是对的吗?
这里有几个问题。 在车内,您有一个应该是FK参考陈列室的字段。但是,这是一个本地int。这意味着它的值为零。 如果你的车对象应引用您的陈列室,那么你就必须用@ManyToOne
@ManyToOne
@JoinColumn(name="showroomId")
private Showroom showroom;
然后你在陈列室改变字段添加到
@OneToMany(mappedBy = "showroom")
@Cascade(value = { org.hibernate.annotations.CascadeType.ALL })
private List<Car> cars = null;
的引用。如果你这样做,你需要明确地在Car中设置参考。 无论哪种方式,showroomId(也是一个本地int)需要去。要么你不应该在你的Car对象中拥有这个字段,并且你只有backref List,否则你需要用正确映射的Entity引用替换它(见上面)。
另一个问题是您生成的列是本机类型。这成为0的值,并且Hibernate不会自动/正确地生成该值。
更改两个实体的主键引用(与getter和setter一起)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
为了从DB成功加载的实体,我也不得不增加一个默认的构造函数用于汽车。
protected Car() {
}
然后你的例子将工作。
我尝试了你的建议,并在执行后返回错误“标记为mappedBy的关联不能像@JoinTable或@JoinColumn那样定义数据库映射” – SheppardDigital
糟糕。是的。 JoinColumn注释属于Car对象内部的Showroom字段定义。我还必须在Car对象内部添加一个默认构造函数,然后才能从数据库加载它们。随着默认consructor(这与可见性降低适用)我的应用程序崩溃。我编辑了我的答案以反映这两点。 –
我已经设法得到这个工作。第一个问题是我的汽车类没有展厅物业。第二个是我保存物体的方式似乎不正确。
我已将课程更改为此..
@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;
}
}
现在保存功能;
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();
所以,如果我先救展厅(不含汽车),确保我抢insertId并将此作为id的陈列室,汽车再次添加到展厅和保存(更新),这应该插入有展厅ID的汽车? – SheppardDigital
查看本教程:http://alextretyakov.blogspot.hk/2013/07/jpa-many-to-many-mappings.html –
谢谢,我来看看。 – SheppardDigital