2009-12-18 15 views
5

Tengo las clases de entidad a continuación. Cuando un usuario se registra por primera vez, solo se proporciona el nombre de usuario y la contraseña, por lo que la lista de cuentas (perfiles de opinión) está vacía. Más tarde, cuando agregan una cuenta, el objeto del usuario se actualiza en el cliente, se pasa al servidor y luego se llama a entityManager.merge (usuario). Cuando el usuario se fusiona, la cuenta se agrega 6 veces a la base de datos y la dirección suministrada se agrega tres veces. No estoy seguro por qué. Me gustaría que la cuenta se agregue una vez y solo se agregue una dirección. ¿Alguna idea sobre lo que puede estar pasando?JPA Merge Is Causing Duplicates

@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

Usted puede dejar cosas por el estilo @Column (name = "id") o @Column (name = "zip") si no va a cambiar los nombres. – whiskeysierra

+0

el servidor activo está predeterminado en todos los nombres de tabla y columna y mi servidor de prueba está predeterminado en minúscula, por lo que parecía más fácil que cambiar la configuración. – chris

+0

¿Encontró una solución? –

Respuesta

0

¿Ha intentado:

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

Creo que debido a dirección de y cuenta han generado Identificación y especifica en cascada causar este problema.

1

Este es un problema conocido con el uso de merge donde las colecciones son listas. Lamentablemente, ahora la solución real aún: HHH-5855

+0

Reparado en la versión 5.0.8 – aorticDefiance

0

Mi solución a este problema fue agregar una función adicional al controlador que actualizaría la fila con una instrucción SQL nativa. Como mi código actualizó una parte o la clave (larga historia, pero sorprendentemente funcionó increíblemente bien) tuve que asegurarme de que no estaba buscando el registro basado en los nuevos valores en el pojo. Aquí está el código:

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(); 
     } 
    } 
}