2014-10-31 79 views
0

我正在尝试使用JBoss Seam和JPA更新实体,但我面临着分离实体这个非常常见的问题。我会解释得更好。使用JBoss Seam的EntityHome合并JPA实体

我有两个相关的简单实体。这个关系映射了注释。请看:

@Entity 
@Table(name = "RATEIO", uniqueConstraints = { @UniqueConstraint(columnNames = { "cd_projeto", "cd_tarefa", "cd_colaborador", "dt_rateio_inicial", 
     "dt_rateio_final" }) }) 
@Audited 
public class Rateio implements java.io.Serializable { 

    private static final long serialVersionUID = 1564844894403478898L; 

    private Long cdRateio; 
    private Colaborador colaborador; 
    private Tarefa tarefa; 
    private Projeto projeto; 
    private Date dtRateioInicial; 
    private Date dtRateioFinal; 

    private boolean flagAtividade; 
    private TipoRateio tipo; 
    private List<DetalheRateio> detalheRateios = new ArrayList<DetalheRateio>(0); 

    public Rateio() { 
    } 

    public Rateio(Long cdRateio, Colaborador colaborador, Projeto projeto, Date dtRateioInicial, Date dtRateioFinal) { 
     this.cdRateio = cdRateio; 
     this.colaborador = colaborador; 
     this.projeto = projeto; 
     this.dtRateioInicial = dtRateioInicial; 
     this.dtRateioFinal = dtRateioFinal; 
    } 

    public Rateio(Long cdRateio, Colaborador colaborador, Projeto projeto, Date dtRateioInicial, Date dtRateioFinal, List<DetalheRateio> detalheRateios) { 
     this.cdRateio = cdRateio; 
     this.colaborador = colaborador; 
     this.projeto = projeto; 
     this.dtRateioInicial = dtRateioInicial; 
     this.dtRateioFinal = dtRateioFinal; 
     this.detalheRateios = detalheRateios; 
    } 

    @Id 
    @SequenceGenerator(name = "sg_RATEIO_SEQ", sequenceName = "RATEIO_SEQ", allocationSize = 1) 
    @GeneratedValue(generator = "sg_RATEIO_SEQ") 
    @Column(name = "CD_RATEIO", nullable = false, scale = 0) 
    public Long getCdRateio() { 
     return this.cdRateio; 
    } 

    public void setCdRateio(Long cdRateio) { 
     this.cdRateio = cdRateio; 
    } 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "CD_COLABORADOR", nullable = true) 
    public Colaborador getColaborador() { 
     return this.colaborador; 
    } 

    public void setColaborador(Colaborador colaborador) { 
     this.colaborador = colaborador; 
    } 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "CD_PROJETO", nullable = true) 
    public Projeto getProjeto() { 
     return this.projeto; 
    } 

    public void setProjeto(Projeto projeto) { 
     this.projeto = projeto; 
    } 

    @Column(name = "DT_RATEIO_INICIAL", nullable = false) 
    public Date getDtRateioInicial() { 
     return this.dtRateioInicial; 
    } 

    public void setDtRateioInicial(Date dtRateioInicial) { 
     this.dtRateioInicial = dtRateioInicial; 
    } 

    @Column(name = "DT_RATEIO_FINAL", nullable = true) 
    public Date getDtRateioFinal() { 
     return this.dtRateioFinal; 
    } 

    public void setDtRateioFinal(Date dtRateioFinal) { 
     this.dtRateioFinal = dtRateioFinal; 
    } 

    @OneToMany(targetEntity=DetalheRateio.class, mappedBy = "rateio") 
    public List<DetalheRateio> getDetalheRateios() { 
     return this.detalheRateios; 
    } 

    public void setDetalheRateios(List<DetalheRateio> detalheRateios) { 
     this.detalheRateios = detalheRateios; 
    } 

    @ManyToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "CD_TAREFA", nullable = true) 
    public Tarefa getTarefa() { 
     return tarefa; 
    } 

    public void setTarefa(Tarefa tarefa) { 
     this.tarefa = tarefa; 
    } 

    @Enumerated(EnumType.ORDINAL) 
    public TipoRateio getTipo() { 
     return tipo; 
    } 

    public void setTipo(TipoRateio tipo) { 
     this.tipo = tipo; 
    } 

    @Transient 
    public boolean isFlagAtividade() { 
     return flagAtividade; 
    } 

    public void setFlagAtividade(boolean flagAtividade) { 
     this.flagAtividade = flagAtividade; 
    } 
} 

我的第二个实体:

@Entity 
@Table(name = "DETALHE_RATEIO") 
@Audited 
public class DetalheRateio implements Serializable { 

    private static final long serialVersionUID = 4109721744851677683L; 

    private Long cdDetalheRateio; 
    private Rateio rateio; 
    private AtividadeOs atividadeOs; 
    private float vlPorcentagem; 

    public DetalheRateio() { 
    } 

    public DetalheRateio(Long cdDetalheRateio, Rateio rateio, AtividadeOs atividadeOs, float vlPorcentagem) { 
     this.cdDetalheRateio = cdDetalheRateio; 
     this.rateio = rateio; 
     this.atividadeOs = atividadeOs; 
     this.vlPorcentagem = vlPorcentagem; 
    } 

    @Id 
    @SequenceGenerator(name = "sg_DET_RATEIO_SEQ", sequenceName = "DET_RATEIO_SEQ", allocationSize = 1) 
    @GeneratedValue(generator = "sg_DET_RATEIO_SEQ") 
    @Column(name = "CD_DETALHE_RATEIO", nullable = false, scale = 0) 
    public Long getCdDetalheRateio() { 
     return this.cdDetalheRateio; 
    } 

    public void setCdDetalheRateio(Long cdDetalheRateio) { 
     this.cdDetalheRateio = cdDetalheRateio; 
    } 

    @ManyToOne(targetEntity = Rateio.class, cascade=CascadeType.ALL) 
    @JoinColumn(name = "CD_RATEIO", nullable = false) 
    public Rateio getRateio() { 
     return this.rateio; 
    } 

    public void setRateio(Rateio rateio) { 
     this.rateio = rateio; 
    } 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "CD_ATIVIDADE_OS", nullable = false) 
    public AtividadeOs getAtividadeOs() { 
     return this.atividadeOs; 
    } 

    public void setAtividadeOs(AtividadeOs atividadeOs) { 
     this.atividadeOs = atividadeOs; 
    } 

    @Column(name = "VL_PORCENTAGEM", nullable = false, precision = 19, scale = 2, columnDefinition = "NUMBER") 
    public float getVlPorcentagem() { 
     return this.vlPorcentagem; 
    } 

    public void setVlPorcentagem(float vlPorcentagem) { 
     this.vlPorcentagem = vlPorcentagem; 
    } 
} 

OK,到目前为止,一切都很好。现在,我有一个从JBoss Seam扩展EntityHome的类,并且这个类试图更新我的实体。这里是代码:

@Name("rateioHome") 
public class RateioHome extends EntityHome<Rateio> { 

    @SuppressWarnings("unchecked") 
    @Override 
    @Transactional 
    public String update() { 
     String result = null; 
     boolean valid = true; 
     if (getPercentualTotal().doubleValue() < 100 || instance.getDetalheRateios().size() < 2) { 
      facesMessages.addFromResourceBundle(Severity.ERROR, "rateio.erro.atividade"); 
      valid = false; 
     } 

     if (instance.getDtRateioFinal() != null && instance.getDtRateioFinal().before(instance.getDtRateioInicial())) { 
      facesMessages.addFromResourceBundle(Severity.ERROR, "rateio.erro.data"); 
      valid = false; 
     } 

     if (valid) { 
      Rateio rateio = super.find(); 
      List<DetalheRateio> detalheRateios = getInstance().getDetalheRateios(); 
      List<DetalheRateio> detalheRateiosBd = rateio.getDetalheRateios(); 
      Map<Long, DetalheRateio> mapDetalheRateio = new HashMap<Long, DetalheRateio>(); 

      if (detalheRateiosBd != null && detalheRateiosBd.size() > 0) { 

       Rateio _rateio = getInstance(); 

       for (DetalheRateio item : detalheRateiosBd) { 

        if (item.getCdDetalheRateio() != null) { 

         item.getRateio().setDtRateioInicial(_rateio.getDtRateioInicial()); 
         item.getRateio().setDtRateioFinal(_rateio.getDtRateioFinal()); 
         mapDetalheRateio.put(item.getCdDetalheRateio(), item); 
        } 
       } 
      } 

      List<DetalheRateio> novos = (List<DetalheRateio>) CollectionUtils.subtract(detalheRateios, detalheRateiosBd); 
      List<DetalheRateio> excluidos = (List<DetalheRateio>) CollectionUtils.subtract(detalheRateiosBd, detalheRateios); 

      detalheRateiosBd.removeAll(excluidos); 
      detalheRateiosBd.addAll(novos); 

      setInstance(rateio); 
      result = super.update(); 
      getEntityManager().flush(); 
     } 
     return result; 
    } 
} 

现在,问题。当我TR更新上线实体:result = super.update();,我面对此异常:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: br.com.entity.DetalheRateio

我试图找到一种方法merge上EntityHome,但我没有发现任何东西。这是我必须支持的遗留代码,我不是JBoss Seam的专家。如果您需要更多信息,请告诉我。

+0

合并()荣获”这个错误是在抱怨孩子DetalheRateio被分离了,也许你在某个地方添加了一个新的实例而没有先坚持它呢? – Gimby 2014-10-31 12:02:22

+0

嗨,我想我在这里分离子对象:'' List detalheRateiosBd = rateio.getDetalheRateios();'。这个对象被更新(值),我将它设置回'Rateio'对象。现在,我如何更新JPA EntityHome内的子对象? – 2014-11-07 12:22:20

回答

0

刚刚找到解决方案。在更新对象Rateio之前,对象列表DetalheRateio必须合并(持续)。我因子评分的对象DetalheRateio为Rateio孩子将自动JPA坚持”我的错所以,我合并手动每个DetalheRateio对象的,我用来做这snipet:。

List<DetalheRateio> novos = (List<DetalheRateio>) CollectionUtils.subtract(detalheRateios, detalheRateiosBd); 
List<DetalheRateio> excluidos = (List<DetalheRateio>) CollectionUtils.subtract(detalheRateiosBd, detalheRateios); 
List<DetalheRateio> detalhesAlterados = new ArrayList<DetalheRateio>(); 

detalheRateiosBd.removeAll(excluidos); 
detalheRateiosBd.addAll(novos); 

for (DetalheRateio detalheExcluido : excluidos) { 
    getEntityManager().remove(detalheExcluido); 
} 

for (DetalheRateio dRateio : detalheRateios) { 
    detalhesAlterados.add(getEntityManager().merge(dRateio)); 
} 

rateio.setDetalheRateios(detalhesAlterados); 
setInstance(rateio); 
result = super.update(); 
getEntityManager().flush();