Beata92 Beata92 - 2 months ago 24
Java Question

Hibernate Cannot add or update a child row: a foreign key constraint fails

When I'm trying to save object into database I got error:

java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`smartphones`.`smartphone`, CONSTRAINT `fk_smartphone_resolution1` FOREIGN KEY (`resolution_id`) REFERENCES `resolution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)





First thing is I have wrong name of references column in
Smartphone
class but I checked and it looks well. Maybe someone figure out what is the reason of this issue?

Short database screenshot


enter image description here

SQL script to create smartphone table

CREATE TABLE IF NOT EXISTS `smartphones`.`smartphone` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NULL DEFAULT NULL,
`resolution_id` INT(11) NOT NULL,
...other
PRIMARY KEY (`id`, `resolution_id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC),
INDEX `fk_smartphone_resolution1_idx` (`resolution_id` ASC),
CONSTRAINT `fk_smartphone_resolution1`
FOREIGN KEY (`resolution_id`)
REFERENCES `smartphones`.`resolution` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)


Smartphone
class but with one relationship object.

package com.project.model;

import javax.persistence.*;

@Entity
public class Smartphone {
private int id;
private String name;
private Resolution resolutionId;

@Id
@Column(name = "id")
public int getId() {
return id;
}

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

@Basic
@Column(name = "name")
public String getName() {
return name;
}

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

@ManyToOne(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
@JoinColumn(name = "resolution_id", referencedColumnName = "id", nullable = false)
public Resolution getResolutionId() {
return resolutionId;
}

public void setResolutionId(Resolution resolutionId) {
this.resolutionId = resolutionId;
}
}


[Edit: Parsing smartphone model and saving into database]

@RequestMapping(value = { "apple" }, method = RequestMethod.GET)
public String parseApple(ModelMap model) {

try {
String appleData = Utilities.getResourceAsString(this, "json/apple.json");

JSONArray array = new JSONArray(appleData);

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();

for (int i = 0; i < array.length(); i++) {
Smartphone smartphone = new Smartphone();

String resolutionValue = array.getJSONObject(i).getString("resolution");
String resolution_w = resolutionValue.split(" ")[0];
String resolution_h = resolutionValue.split(" ")[2];
Resolution resolution = new Resolution();
resolution.setHeight(Integer.valueOf(resolution_h));
resolution.setWidth(Integer.valueOf(resolution_w));
resolution.setTypeId(typeService.findByCode(session, Resolution.serialId));
session.save(resolution);

smartphone.setResolutionId(resolution);
//other

session.save(smartphone);
break;
}
transaction.commit();
sessionFactory.close();

} catch (IOException e) {
e.printStackTrace();
}

return "index";
}


[Edit: Added] Resolution class:

@Entity
public class Resolution {
public static final int serialId = 106;

private int id;
private Integer height;
private Integer width;
private Type typeId;
private Collection<Smartphone> resolutionId;

@Id
@Column(name = "id")
public int getId() {
return id;
}

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

@Basic
@Column(name = "height")
public Integer getHeight() {
return height;
}

public void setHeight(Integer height) {
this.height = height;
}

@Basic
@Column(name = "width")
public Integer getWidth() {
return width;
}

public void setWidth(Integer width) {
this.width = width;
}

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "type_id", referencedColumnName = "id", nullable = false)
public Type getTypeId() {
return typeId;
}

public void setTypeId(Type typeId) {
this.typeId = typeId;
}

@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(mappedBy = "resolutionId")
public Collection<Smartphone> getResolutionId() {
return resolutionId;
}

public void setResolutionId(Collection<Smartphone> resolutionId) {
this.resolutionId = resolutionId;
}
}

Answer

Almost well. You have to add above getId() method for Resolution class and similar code below. Probably your resolution object has always 0 as id after save method call.

@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)
Comments