com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException重复条目

时间:2017-10-11 13:24:25

标签: java mysql hibernate spring-boot

我使用带有MySQL数据库的Spring启动项目并提供了实体,

IP地址实体

@Entity
public class IpAddress {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "IP_ADDR_ID")
    private Long id;

    @Column(name = "IP_ADDRESS")
    @NotEmpty
    private String address;


    @JsonIgnore
    @ManyToMany(cascade = CascadeType.ALL, mappedBy = "ipAddresses")
    private List<HttpInfoMessage> httpInfoMessages = new ArrayList<>();

    public IpAddress() {
    }

    public IpAddress(String address) {
        this.address = address;
    }

    public IpAddress(String address, List<HttpInfoMessage> httpInfoMessages) {
        this.address = address;
        this.httpInfoMessages = httpInfoMessages;
    }

    public Long getId() {
        return id;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public List<HttpInfoMessage> getHttpInfoMessages() {
        return httpInfoMessages;
    }

    public void setHttpInfoMessages(List<HttpInfoMessage> httpInfoMessages) {
        this.httpInfoMessages = httpInfoMessages;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof IpAddress)) return false;

        IpAddress ipAddress = (IpAddress) o;

        if (!getId().equals(ipAddress.getId())) return false;
        return getAddress().equals(ipAddress.getAddress());
    }

    @Override
    public int hashCode() {
        int result = getId().hashCode();
        result = 31 * result + getAddress().hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "IpAddress{" +
                "id=" + id +
                ", address='" + address + '\'' +
                '}';
    }
}

Http消息实体

@Entity
public class HttpInfoMessage {

    @Id
//    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "STATUS_ID")
    private Long statusId;

    @Column(name = "STATUS")
    @NotEmpty
    private String status;

    public HttpInfoMessage() {

    }

    public HttpInfoMessage(String status) {
        this.status = status;
    }

    public HttpInfoMessage(Long statusId, String status) {
        this.statusId = statusId;
        this.status = status;
    }

    public HttpInfoMessage(Long statusId, String status, List<IpAddress> ipAddresses) {
        this.statusId = statusId;
        this.status = status;
        this.ipAddresses = ipAddresses;
    }

    public Long getStatusId() {
        return statusId;
    }

    public void setStatusId(Long statusId) {
        this.statusId = statusId;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    //    @ManyToMany(cascade = CascadeType.ALL, mappedBy = "httpInfoMessages")
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "IP_ADDR_STATUS",
            joinColumns = @JoinColumn(name = "STATUS_ID", referencedColumnName = "STATUS_ID"),
            inverseJoinColumns = @JoinColumn(name = "IP_ADDRESS_ID", referencedColumnName = "IP_ADDR_ID"))
    private List<IpAddress> ipAddresses = new ArrayList<>();

    public List<IpAddress> getIpAddresses() {
        return ipAddresses;
    }

    public void setIpAddresses(List<IpAddress> ipAddresses) {
        this.ipAddresses = ipAddresses;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof HttpInfoMessage)) return false;

        HttpInfoMessage httpInfoMessage1 = (HttpInfoMessage) o;

        if (!getStatusId().equals(httpInfoMessage1.getStatusId())) return false;
        return getStatus().equals(httpInfoMessage1.getStatus());
    }

    @Override
    public int hashCode() {
        int result = getStatusId().hashCode();
        result = 31 * result + getStatus().hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "Status{" +
                "statusId=" + statusId +
                ", status='" + status + '\'' +
                '}';
    }
}

我从文本文件中读取服务器日志条目并对它们执行一些操作,最终得到List<IpAddress>

获得List<IpAddress>之后,我打印出来只是为了显示,

The IP list size is = 5

IP address = IpAddress{id=null, address='177.132.239.67'}
Status{statusId=403, status='403_Forbidden'}
Status{statusId=404, status='404_Not Found'}
Status{statusId=405, status='405_Method Not Allowed'}
Status{statusId=406, status='406_Not Acceptable'}

IP address = IpAddress{id=null, address='178.133.239.67'}
Status{statusId=403, status='403_Forbidden'}
Status{statusId=404, status='404_Not Found'}
Status{statusId=405, status='405_Method Not Allowed'}
Status{statusId=406, status='406_Not Acceptable'}

IP address = IpAddress{id=null, address='175.130.239.67'}
Status{statusId=403, status='403_Forbidden'}
Status{statusId=404, status='404_Not Found'}
Status{statusId=405, status='405_Method Not Allowed'}
Status{statusId=406, status='406_Not Acceptable'}

IP address = IpAddress{id=null, address='176.131.239.67'}
Status{statusId=403, status='403_Forbidden'}
Status{statusId=404, status='404_Not Found'}
Status{statusId=405, status='405_Method Not Allowed'}
Status{statusId=406, status='406_Not Acceptable'}

IP address = IpAddress{id=null, address='174.129.239.67'}
Status{statusId=403, status='403_Forbidden'}
Status{statusId=404, status='404_Not Found'}
Status{statusId=405, status='405_Method Not Allowed'}
Status{statusId=406, status='406_Not Acceptable'}

然后我尝试通过迭代来保存所有条目,

ipAddresses.forEach(
                ipAddress -> {
                    ipAddressService.save(ipAddress);
                }
        );

我在保存条目时收到错误

java.lang.IllegalStateException: Failed to execute CommandLineRunner

Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '403' for key 'PRIMARY'

如果需要,我可以提供更多信息

3 个答案:

答案 0 :(得分:1)

在您的httpService-Entity中,statusId字段是主键。您的testdata在每个statusId - Block中的IpAddress中设置了值403-406。如果从statusId中删除值并将它们设置为null,它应该可以正常工作。

答案 1 :(得分:1)

您正尝试将非唯一的http状态代码作为Id的statusId,这是唯一的。

由于您提供了实体并且无法更改它们,因此您必须确保正确插入值作为状态。对于我这样的实体,您可以将一个技术(生成)ID发送到statusId,并将状态名称(&#39; 403_Forbidden&#39;或简称为&#39; 403&#39;)添加到状态列。

答案 2 :(得分:1)

每个IpAddress对象都有一个HttpInfoMessage对象列表,它使用statusId字段作为数据库中的ID。 ID必须是唯一的。

但是对这些集合使用CascadeType.ALL,这意味着也会保存HttpInfoMessage对象。

因此,当您尝试第二次保存Status{statusId=403, status='403_Forbidden'}时,您会收到异常,因为该ID已经存在。这是简单的数据库内容,你必须解决这个问题。怎么样,取决于你想做什么。