简体   繁体   中英

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

在此处输入图像描述

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;
    }
}

You're trying to add/update a row to resolution that does not have a valid value for the id field based on the values stored in smartphone .
You must first insert the row to your resolution table.

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)

Add @Id @GeneratedValue(strategy = GenerationType.IDENTITY)

Annotations in Model class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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