【问题标题】:Hibernate Cannot add or update a child row: a foreign key constraint failsHibernate 无法添加或更新子行:外键约束失败
【发布时间】:2016-09-12 18:24:41
【问题描述】:

当我尝试将对象保存到数据库时出现错误:

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)


第一件事是我在Smartphone 类中的引用列名称错误,但我检查了一下,它看起来不错。也许有人弄清楚这个问题的原因是什么?

数据库截图

用于创建智能手机表的 SQL 脚本

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 类,但只有一个关系对象。

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

[编辑:解析智能手机型号并保存到数据库]

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

[编辑:添加]分辨率类:

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

【问题讨论】:

  • 当你保存“智能手机”时,它引用的“解决方案”应该是数据库中的持久实体。
  • 是的,我正在使用 session.save()。我应该使用新事务来保存新对象吗?请检查。我添加了源代码。
  • 对我来说也是,但它不起作用。
  • 我添加了Resolution类源代码。

标签: java mysql spring hibernate


【解决方案1】:

差不多好了。您必须为Resolution 类和下面的类似代码添加上面的getId() 方法。可能您的 resolution 对象在保存方法调用后始终为 0 作为 id

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

【讨论】:

    【解决方案2】:

    您正在尝试 add/updateresolution 的一行,该行没有基于 smartphone 中存储的值的 id 字段的有效值。
    您必须先将该行插入到您的 resolution 表中。

    【讨论】:

    • 是的,我正在使用session.save()。我应该使用新事务来保存新对象吗?
    猜你喜欢
    • 2011-08-03
    • 1970-01-01
    • 2020-10-04
    相关资源
    最近更新 更多