2009-12-18 81 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(); 
     } 
    } 
}