JPA 中的参照完整性约束违反错误

Posted

技术标签:

【中文标题】JPA 中的参照完整性约束违反错误【英文标题】:Referential integrity constraint violation error in JPA 【发布时间】:2017-12-25 20:03:45 【问题描述】:

我正在尝试解析 Web 请求并保存到数据库。我有 3 个模型,第一个节点是 virtualDocument。这是 uniq 表(根据请求 url)。 VirtualRequest 表具有所有 erquest 主体,而 HttpHeaderList 表根据其 virtualRequest bean id 具有所有 thhp 标头。

当我尝试保存我得到的第一个日志时,出现这样的错误;

org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK1TW2G47F7A47580KQVMDJWGBQ: PUBLIC.T_VIRTUAL_REQUEST FOREIGN KEY(REQUEST_ID) REFERENCES PUBLIC.T_VIRTUAL_DOCUMENT(DOCUMENT_ID) (65)"; SQL statement:
insert into t_virtual_request (request_id, media_type, method_type, request_url) values (null, ?, ?, ?) [23506-192]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.192.jar:1.4.192]

这里是 VirtualDocument bean

@Entity
@Table(name = "t_virtual_document")
public class VirtualDocument 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "document_id")
    private long documentId;

    @Column(name = "real_url", unique = true)
    private String realURL; //uniq

    @Column(name = "virtual_url", unique = true)
    private String virtualURL; //uniq

    @Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
    private String simulationMode;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "request_id")
    private List<VirtualRequest> requestList;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "response_id")
    private List<VirtualResponse> responseList;

   //getter setter without any annotation

这里是 VirtualRequest bean;

@Entity
@Table(name = "t_virtual_request")
public class VirtualRequest 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "request_id")
    private long requestId;

    @Column(name = "request_url")
    private String requestURL;

    @Column(name = "method_type")
    private String methodType;

    @Column(name = "media_type")
    private String mediaType;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "header_id")
    private List<HttpHeaderList> requestHeaders;

   //getter setter without any annotation

这里是 HeaderList bean;

@Entity
@Table(name = "t_http_headers")
public class HttpHeaderList 

    @Id
    @Column(name = "header_id")
    private long headerId;

    @Column(name = "header_key")
    private String headerKey;

    @Column(name = "header_value")
    private String headerValue;

【问题讨论】:

看起来你的 JPA 映射不正确。如果您希望每个 VirtualDocument 有多个请求,则需要从 VirtualRequest 到文档的外键。然后,您将在 @OneToMany 注释中使用 mappedBy 参数将点 JPA 告知外键属性。 mappedBy 参数可以是东西还是必须是字段? 请看我的回答。通过点映射到拥有关系的实体中的字段。 【参考方案1】:

我认为这是你想要的:

@Entity
@Table(name = "t_virtual_document")
public class VirtualDocument 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "document_id")
    private long documentId;

    @Column(name = "real_url", unique = true)
    private String realURL; //uniq

    @Column(name = "virtual_url", unique = true)
    private String virtualURL; //uniq

    @Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
    private String simulationMode;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
    private List<VirtualRequest> requestList;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
    // Note the mappedBy parameter. This points to the property in the entity that owns the relationship (in this case the VirtualResponse).
    private List<VirtualResponse> responseList;

   //getter setter without any annotation


@Entity
@Table(name = "t_virtual_request")
public class VirtualRequest 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "request_id")
    private long requestId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "document_id")
    private VirtualDocument virtualDocument;

    @Column(name = "request_url")
    private String requestURL;

    @Column(name = "method_type")
    private String methodType;

    @Column(name = "media_type")
    private String mediaType;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualRequest")
    private List<HttpHeaderList> requestHeaders;

   //getter setter without any annotation


@Entity
@Table(name = "t_http_headers")
public class HttpHeader  /*Note this is a more appropriate name for the entity since it holds the data of a single header.*/

    @Id
    @Column(name = "header_id")
    private long headerId;

    @Column(name = "header_key")
    private String headerKey;

    @Column(name = "header_value")
    private String headerValue;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "request_id")
    private VirtualRequest virtualRequest

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "response_id")
    private VirtualResponse virtualResponse;

更新了答案以添加将标头映射到请求实体。

【讨论】:

@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "document_id") private long documentId;在这个字段类型中,必须是long还是VirtualDocument? 不.. 我的错。它需要与实体类型相同。让我解决这个问题。 抱歉有问题,但是我对这些映射主题有很大的问题,最后一个问题,我的 HttpHeaderList bean 和其他请求-响应 bean 需要映射吗?如果是的话怎么办?因为我得到一个错误标记为 mappedBy 的关联不能定义像 JoinTable 或 JoinColumn 这样的数据库映射:VirtualResponse.responseHeaders 试试更新的代码。始终考虑哪个实体拥有关系(外键)。该实体具有 JoinColumn 注释。目标实体有 OneToMany 和 mappedBy 参数。 正确!您不能在同一个字段中同时拥有两者。

以上是关于JPA 中的参照完整性约束违反错误的主要内容,如果未能解决你的问题,请参考以下文章

H2 更新时违反参照完整性约束

H2 参照完整性约束违反

org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:违反参照完整性约束

该值违反了列的完整性约束

ORA-02292: 违反完整性约束

SQLSTATE [23000]:违反完整性约束:1217