2017-10-11 4 views
0

Je travaille avec un projet de démarrage Spring avec base de données MySQL et les entités sont fournis,com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException entrée en double

L'entité adresse 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 + '\'' + 
       '}'; 
    } 
} 

Le Http entité message,

@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 + '\'' + 
       '}'; 
    } 
} 

Je lis les entrées du journal du serveur à partir d'un fichier texte et effectuer quelques manipulations sur eux et finalement, je reçois le List<IpAddress>.

Après que je reçois le List<IpAddress>, je les ai imprimés juste pour montrer,

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

J'ai ensuite essayé de sauver toutes les entrées par itérer à travers eux,

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

je reçois l'erreur au temps de sauver les entrées,

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' 

Je peux fournir plus d'informations si besoin d

Répondre

1

Chaque objet IpAddress possède une liste d'objets HttpInfoMessage qui utilise le champ statusId comme ID dans la base de données. Un identifiant doit être unique. Mais vous utilisez le CascadeType.ALL pour ces collections, ce qui signifie que les objets HttpInfoMessage seront également sauvegardés. Donc, lorsque vous essayez d'enregistrer le Status{statusId=403, status='403_Forbidden'} une deuxième fois vous obtenez l'exception, car l'ID existe déjà. C'est une base de données simple et vous devez résoudre ce problème. Comment, dépend de ce que vous voulez faire.

+0

Je suppose que l'attribution d'une colonne 'id'' IpAddress' 'dans la table' HttpInfoMessage' résoudra le problème bien que je me demande comment le faire. Dans ce temps, il va enregistrer comme 'Status {statusId = 403, status = '403_Forbidden', id = 1}', 'Statut {statusId = 403, status = '403_Forbidden', id = 2}' etc et sera unique . J'ouvrirai savoir n'importe quelle autre meilleure solution aussi bien. – Arefe

+0

Si j'utilise 'CascadeType.MERGE' ou' CascadeType.DETACH', il ne remplira que la table 'ip_address'. Je préférerais remplir toutes les tables si possible. S'il vous plaît avis – Arefe

+0

Ce que vous suggérez est une relation OneToMany. Regardez ici https: //en.wikibooks.org/wiki/Java_Persistence/OneToMany, si vous voulez savoir comment le faire. Pour moi, les valeurs sont statiques, alors j'utiliserais une table enum ou database avec des valeurs énumérées –

1

Dans votre httpService-Entity, le champ statusId est la clé primaire. Votre testdata a les valeurs 403-406 définies dans statusId dans chaque IpAddress -Block. Si vous supprimez les valeurs de statusId et que vous les définissez sur null, cela devrait fonctionner.

+0

Comment supprimer les valeurs de 'statusId'? – Arefe

+0

Est-ce que vous créez manuellement la liste ? Ensuite, vous définissez également la valeur sur Status.statusId manuellement. Sinon, vous devez parcourir tous les éléments d'état et appeler sth. comme status.setStatusId = null. –

1

Vous tentez de mettre des codes d'état HTTP non uniques en tant qu'ID statusId de l'ID qui est unique.

Comme vos entités sont fournies et que vous ne pouvez pas les modifier, vous devez vous assurer que vous insérez correctement des valeurs en tant qu'état. Pour moi, avec une telle entité, vous pouvez mettre un ID technique (généré) à statusId et un nom de votre statut ('403_Forbidden' ou simplement '403') dans la colonne status.