2009-12-18 6 views
5

У меня есть классы сущностей ниже. Когда пользователь сначала регистрируется, предоставляются только имя пользователя и пароль, поэтому список учетных записей (думаю, профили) пуст. Позже, когда они добавляют учетную запись, пользовательский объект обновляется в клиенте, передается на сервер, а затем вызывается entityManager.merge (пользователь). Когда пользователь сливается, учетная запись добавляется 6 раз в базу данных, а указанный адрес добавляется три раза. Я не знаю, почему. Я бы хотел, чтобы учетная запись была добавлена ​​один раз и добавлен только один адрес. Любые идеи о том, что может произойти?JPA Merge вызывает дубликаты

@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

Вы можете оставить такие вещи, как @Column (имя = "ID") или @Column (имя = "почтовый") , если вы не меняете имена. – whiskeysierra

+0

сервер работает по умолчанию для всех заголовков таблиц и имен столбцов, а мой тестовый сервер по умолчанию имеет строчные значения, поэтому это проще, чем изменение настроек. – chris

+0

Вы нашли решение? –

ответ

0

Вы пробовали:

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

Я думаю, потому что адрес и счет сгенерировал идентификатор и указать каскадные вызвать эту проблему.

1

Это известная проблема с использованием слияния, где коллекции являются списками. К сожалению, сейчас исправлено: HHH-5855

+0

Исправлено в версии 5.0.8 – aorticDefiance

0

Мое решение этой проблемы состояло в том, чтобы добавить дополнительную функцию к контроллеру, который обновил бы строку с помощью родного оператора SQL. Поскольку мой код обновил часть или ключ (длинный рассказ, но на удивление работал удивительно хорошо), я должен был убедиться, что я не ищу запись, основанную на новых значениях в pojo. вот код:

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(); 
     } 
    } 
} 
Смежные вопросы