2009-12-18 79 views
5

我有下面的實體類。當用戶首次註冊時,只提供用戶名和密碼,所以帳戶列表(認爲個人資料)是空的。稍後,當他們添加一個帳戶時,用戶對象在客戶端中更新,傳遞給服務器,然後調用entityManager.merge(user)。當用戶合併時,帳戶被添加6次到數據庫,並且提供的地址被添加三次。我不知道爲什麼。我想要添加帳戶一次,只添加一個地址。關於可能發生什麼的任何想法?JPA合併造成重複

@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(name = 「ID」)或 @Column(name = 「拉鍊」) 掉落的東西,如果你不改變文件名。 – whiskeysierra 2009-12-18 22:56:19

+0

實時服務器默認爲全部大寫表格和列名稱,而我的測試服務器默認爲小寫字母,因此看起來比更改設置更容易。 – chris 2009-12-18 23:00:39

+0

您是否找到解決方案? – 2011-05-19 16:36:59

回答

0

您是否嘗試過:

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

我想是因爲地址賬號已生成的ID,並指定級聯導致此問題。

1

這是使用合併的已知問題,其中集合是列表。不幸的是,現在真正的修復尚未完成:HHH-5855

+0

已在5.0.8版中修復 – aorticDefiance 2017-08-08 14:38:51

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