【问题标题】:Why is this causing java.sql.SQLIntegrityConstraintViolationException?为什么这会导致 java.sql.SQLIntegrityConstraintViolationException?
【发布时间】:2013-11-06 08:53:06
【问题描述】:

我的应用有一个实体类(Ativo),带有这个属性和 JPA 注释:

@JoinColumn(name = "BOLSA", referencedColumnName = "ID")
@ManyToOne(optional = false, cascade = {CascadeType.PERSIST})
private Bolsa bolsa;

当我尝试持久化实体类(Ativo)时,抛出此异常:

内部异常:java.sql.SQLIntegrityConstraintViolationException:该语句被中止,因为它会导致唯一或主键约束或由“BOLSA”上定义的“SQL131102225757700”标识的唯一索引中的重复键值。

我不明白我的代码有什么问题。如果这应该只是现有对象的外键,为什么还要尝试创建 Bolsa 类型的新对象??


Ativo 类的标题:

@Entity
@Table(name = "ATIVO")
public class Ativo implements EntityInterface<Ativo>, Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "ID")
    private Long id;

    @Basic(optional = false)
    @Column(name = "CODIGO", unique=true, nullable = false)
    private String codigo;

    @Basic(optional = false)
    @Column(name = "TIPO_MERCADO", nullable = false)
    private String tipoMercado;

    @Column(name = "DESCRICAO", nullable = false, length = 10000)
    private String descricao;

    @JoinColumn(name = "BOLSA", referencedColumnName = "ID")
    @ManyToOne(optional = false, cascade = {CascadeType.PERSIST})
    private Bolsa bolsa;

Bolsa 类的标题:

@Entity
@Table(name = "BOLSA")
public class Bolsa implements EntityInterface<Bolsa>, Serializable, Comparable<Bolsa> {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "ID")
    private Long id;

    @Basic(optional = false)
    @Column(name = "NOME", unique = true, nullable = false)
    private String nome;

    @Column(name = "DESCRICAO", nullable=false, length = 10000)
    private String descricao;

【问题讨论】:

  • 您对错误有什么不明白的地方?
  • 我不明白我的代码有什么问题。如果这应该只是现有对象的外键,为什么还要尝试创建 Bolsa 类型的新对象??
  • 尝试从ManyToOne中删除cascade = {CascadeType.PERSIST}...
  • 感谢@AhsanShah,删除它可以工作的级联。如果您愿意,可以将其发布为答案。
  • 恭喜@ceklock。我现在将发布一些解释供您参考。

标签: java jpa


【解决方案1】:

错误消息很明确:您正在尝试插入包含数据库中已存在的id 的行,因此会发生完整性约束违规(重复的主键)。

检查您的代码,即设置id 的部分,并确保它使用唯一标识符。或者使用 id 字段中的注释每次自动生成一个新密钥。或者定义一个数据库序列来执行此操作。

【讨论】:

  • 是的,但是为什么会这样呢?不是我,是 JPA 试图这样做,为什么??
  • @ceklock 用这么少的信息很难判断,贴出相关代码(id是如何定义的,你是如何插入行的,等等)
  • 正如@Ahsan Shah 所发布的,真正的问题是级联。谢谢你的回答,也很有帮助。
【解决方案2】:

按照 cmets 中的建议,从以下关系中删除 cascade = {CascadeType.PERSIST} 将起作用。

@JoinColumn(name = "BOLSA", referencedColumnName = "ID")
@ManyToOne(optional = false, cascade = {CascadeType.PERSIST})
private Bolsa bolsa;

原因是,Cascade Persist 负责通过传递持久性为您将内容放入数据库,因此您不必显式持久化父级(在您的情况下为“Bolsa”)。但是,在持久化之前维护对象的内存状态始终是您的责任。

我怀疑(因为从提供的片段中不清楚)您在保存 Ativo 之前明确地保留了 Bolsa 对象,因此通过删除级联持久约束来解决异常。

【讨论】:

    【解决方案3】:

    错误消息为您提供了足够的信息来继续挖掘:

    a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL131102225757700'

    它声明它是主键或唯一键约束,并且鉴于您的映射指示的唯一约束(以及我看不出映射本身有任何问题的事实),我猜想它违反了唯一键约束,例如 nome 字段。但是,错误消息给了我们更多信息,那就是被违反的约束的名称:SQL131102225757700。所以,你需要做的是弄清楚这个约束适用于哪一列,一旦你这样做了,我猜你会更接近于找出错误。 (具体怎么做取决于你的数据库提供商,谷歌一下吧..)

    【讨论】:

    • 正如@Ahsan Shah 所发布的,真正的问题是级联。谢谢你的回答,也很有帮助。
    猜你喜欢
    • 2013-02-25
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 2017-04-26
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    相关资源
    最近更新 更多