【问题标题】:Merge JPA Entity using EntityHome from JBoss Seam使用 JBoss Seam 中的 EntityHome 合并 JPA 实体
【发布时间】:2014-10-31 11:17:06
【问题描述】:

我正在尝试使用 JBoss Seam 和 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;
    }
}

好的,到目前为止,一切都很好。现在,我有一个从 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;
    }
}

现在,问题来了。当我在线更新实体时:result = super.update();,我遇到了这个异常:

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

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

【问题讨论】:

  • merge() 将无济于事,因为您的 Ratio 实体实际上是受管理的。该错误是抱怨一个孩子 DetalheRateio 被分离。也许您是在某处添加一个新实例而没有先将其持久化?
  • 嗨。我想我在这里分离子对象:List&lt;DetalheRateio&gt; detalheRateiosBd = rateio.getDetalheRateios();。此对象已更新(值),我将其设置回 Rateio 对象。现在,我如何在 JPA 上更新 EntityHome 中的子对象?

标签: java hibernate jpa seam2


【解决方案1】:

刚刚找到解决方案。对象DetalheRateio 的列表必须在更新对象Rateio 之前合并(持久化)。我坚持认为对象 DetalheRateio 作为Rateio 子对象将“由 JPA 自动保存。我的错误。所以,我手动合并了每个 DetalheRateio 对象。我曾经这样做的片段:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-17
    • 2012-01-12
    • 2013-11-13
    • 2016-02-10
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多