2009-12-18 5 views
5

J'ai les classes d'entités ci-dessous. Lorsqu'un utilisateur s'enregistre pour la première fois, seuls le nom d'utilisateur et le mot de passe sont fournis, de sorte que la liste des comptes (pensez aux profils) est vide. Plus tard, lorsqu'ils ajoutent un compte, l'objet utilisateur est mis à jour dans le client, transmis au serveur, puis entityManager.merge (utilisateur) est appelé. Lorsque l'utilisateur est fusionné, le compte est ajouté 6 fois à la base de données et l'adresse fournie est ajoutée trois fois. Je ne suis pas sûr pourquoi. Je voudrais que le compte soit ajouté une fois et qu'une seule adresse soit ajoutée. Des idées sur ce qui pourrait se passer?JPA Merge provoque des doublons

@Entity 
public class User implements Serializable { 

    private static final long serialVersionUID = 1L; 

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

    @OneToMany(cascade=CascadeType.ALL) 
    @JoinTable(name="user_accounts") 
    private List<Account> accounts; 

    //...getters and setters ... 
} 




@Entity 
public class Account implements Serializable { 

    private static final long serialVersionUID = 1L; 

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

    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name="address") 
    private Address address; 

    //...getters and setters... 

} 



@Entity 
public class Address implements Serializable { 

    private static final long serialVersionUID = 1L; 

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

    @Column(name="street") 
    private String street; 

    @Column(name="city") 
    private String city; 

    @Column(name="state") 
    private String state; 

    @Column(name="zip") 
    private String zip; 

    //...getters and setters... 
} 
+0

Vous pouvez déposer des trucs comme @Column (name = "id") ou @Column (name = "zip") si vous ne changez pas les noms. – whiskeysierra

+0

le serveur live utilise par défaut tous les noms de colonnes et de colonnes et mon serveur de test est par défaut en minuscules, donc cela semblait plus facile que de changer les paramètres. – chris

+0

Avez-vous trouvé une solution? –

Répondre

0

Avez-vous essayé de:

persist(address) 
account.setAddress(address) 
persist(account) 
user.setAccount(account) 
merge(user) 

Je pense que adresse et compte ont généré id et que vous spécifiez cascade causer ce problème.

1

Il s'agit d'un problème connu lié à l'utilisation de la fusion lorsque les collections sont des listes. Malheureusement maintenant la vraie solution encore: HHH-5855

+0

Fixé dans la version 5.0.8 – aorticDefiance

0

Ma solution à ce problème était d'ajouter une fonction supplémentaire au contrôleur qui mettrait à jour la ligne avec une instruction SQL native. Depuis mon code mis à jour partie ou la clé (longue histoire, mais étonnamment travaillé incroyablement bien), je devais m'assurer que je ne cherchais pas l'enregistrement basé sur les nouvelles valeurs dans le pojo. voici le code:

public void editSQLUpdate(Reportinfo reportinfo) throws NonexistentEntityException, Exception { 
    EntityManager em = null; 
    try { 
     em = getEntityManager(); 
     em.getTransaction().begin(); 
     String qry = "UPDATE `boeaudit`.`reportinfo` " 
       + "SET " 
       + "`author` = '" + reportinfo.getAuthor() + "'," 
       + "`db_account` = '" + reportinfo.getDbAccount() + "'," 
       + "`db_schema_name` = '" + reportinfo.getDbSchemaName() + "'," 
       + "`descriptions` = '" + reportinfo.getDescriptions() + "'," 
       + "`DLL` = '" + reportinfo.getDll() + "'," 
       + "`parent_folder` = " + reportinfo.getParentFolder() + "," 
       + "`path` = '" + reportinfo.getPath() + "'," 
       + "`report_title` = '" + reportinfo.getReportTitle() + "'," 
       + "`report_id` = " + reportinfo.getReportinfoPK().getReportId() + "," 
       + "`env` = " + reportinfo.getReportinfoPK().getEnv() + "," 
       + "`db_server` = '" + reportinfo.getReportinfoPK().getDbServer() + "'," 
       + "`seq` = " + reportinfo.getReportinfoPK().getSeq() 
       + " WHERE `report_id` = " + reportinfo.getReportinfoPK().getReportId() 
       + " AND `env` = " + reportinfo.getReportinfoPK().getEnv() 
       + " AND `db_server` = '-'" //this is the initial value of the record and the update value differs, so if we pass the new value the record will not be found. ;) 
       + " AND `seq` = "+ reportinfo.getReportinfoPK().getSeq(); 
     Query nq = em.createNativeQuery(qry); 
     int outcome = nq.executeUpdate(); //not doing anything with outcome, but should be used to determine the result of the operation... 
     em.getTransaction().commit(); 
    } catch (Exception ex) { 
     String msg = ex.getLocalizedMessage(); 
     if (msg == null || msg.length() == 0) { 
      ReportinfoPK id = reportinfo.getReportinfoPK(); 
      if (findReportinfo(id) == null) { 
       throw new NonexistentEntityException("The reportinfo with id " + id + " no longer exists."); 
      } 
     } 
     throw ex; 
    } finally { 
     if (em != null) { 
      em.close(); 
     } 
    } 
}