延迟加载应在需要时加载数据

时间:2013-11-12 00:25:16

标签: java hibernate jpa

嗯,在我的概念中(如果我错了,请纠正我)延迟加载应该是这样的:

想象一下,我有一个对象“卖”和另一个“Itens”,我可以这样做:sell.getItens()或sell.setItens(),只是为了ilustrate。因此,当我使用SQL语句时,我只需加载SELL而不使用itens,如下所示:“SELECT * FROM SELL”。

但是在我尝试做的代码的某个地方:“sell.getItens()。get(0).getPrice()”,JPA / Hibernate必须立即加载来自Sell的所有itens,因为这是一个“需求加载“。

我是对的吗?如果是的话,这对我不起作用。

编辑1: 更具体地说,当我尝试在JSF中的dataTable中使用我的“itens”时出现错误,请查看代码:

<p:dataTable rowKey="#{item.id}" var="item"
                            value="#{consultaMB.consulta.itens}"
                            emptyMessage="Não foi encontrado nenhum registro"
                            id="dataTableItensConsulta"
                            selection="#{consultaMB.itemConsulta}" selectionMode="single"
                            rowIndexVar="rowIndex"
                            rowStyleClass="#{(rowIndex mod 2) eq 0 ? 'first-row' : 'second-row'}">

错误是:rowKey =“#{item.id}”:在类型org.hibernate.collection.PersistentSet上找不到属性'id'

编辑2: 这是我完整的“Consulta”课程,有了itens。

@Entity
@NamedQueries(value = {
        @NamedQuery(name = "Consulta.findByOrcamento", query = "SELECT c FROM Consulta c "
                + "JOIN FETCH c.orcamento "
                + "JOIN FETCH c.situacao "
                + "WHERE c.orcamento.id = :idOrcamento "
                + "ORDER BY c.dataHoraAgendada desc"),
        @NamedQuery(name = "Consulta.findItensByConsulta", query = "SELECT c.itens FROM Consulta c "
                + "JOIN c.itens " + "WHERE c.id = :idConsulta"),
        @NamedQuery(name = "Consulta.findAllCompleto", query = "SELECT c FROM Consulta c "
                + "JOIN FETCH c.orcamento "
                + "JOIN FETCH c.situacao "
                + "ORDER BY c.dataHoraAgendada desc") })
@Table(name = "consulta")
public class Consulta extends AbstractBean {

    public Consulta() {
        this.itens = new HashSet<ItemOrcamento>();
        this.itensConcluidos = new HashSet<ItemOrcamento>();
        this.fotos = new ArrayList<FotoConsulta>();
    }

    @Transient
    public static final String FIND_BY_ORCAMENTO = "Consulta.findByOrcamento";
    @Transient
    public static final String FIND_ALL_COMPLETO = "Consulta.findAllCompleto";
    @Transient
    public static final String FIND_ITENS_BY_CONSULTA = "Consulta.findItensByConsulta";

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_orcamento")
    private Orcamento orcamento;

    @Column(name = "data_hora_agendada")
    @Temporal(value = TemporalType.TIMESTAMP)
    private Date dataHoraAgendada;

    @ManyToMany(fetch = javax.persistence.FetchType.LAZY)
    @JoinTable(name = "item_consulta", joinColumns = { @JoinColumn(name = "id_consulta") }, inverseJoinColumns = { @JoinColumn(name = "id_item_orcamento") })
    private Set<ItemOrcamento> itens;

    @ManyToMany(fetch = javax.persistence.FetchType.LAZY)
    @JoinTable(name = "item_concluido_consulta", joinColumns = { @JoinColumn(name = "id_item_orcamento", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "id_consulta", nullable = false, updatable = false) })
    private Set<ItemOrcamento> itensConcluidos;

    @Column
    private String observacoes;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "id_situacao")
    private SituacaoConsulta situacao;

    @Column(name = "motivo_reagendamento")
    private String motivoReagendamento;

    @Column(name = "motivo_cancelamento")
    private String movitoCancelamento;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "consulta", targetEntity = FotoConsulta.class)
    @Cascade({ org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    private List<FotoConsulta> fotos;

    public Orcamento getOrcamento() {
        return orcamento;
    }

    public void setOrcamento(Orcamento orcamento) {
        this.orcamento = orcamento;
    }

    public Date getDataHoraAgendada() {
        return dataHoraAgendada;
    }

    public void setDataHoraAgendada(Date dataHoraAgendada) {
        this.dataHoraAgendada = dataHoraAgendada;
    }

    public Set<ItemOrcamento> getItens() {
        return itens;
    }

    public void setItens(Set<ItemOrcamento> itens) {
        this.itens = itens;
    }

    public void addItem(ItemOrcamento item) {
        this.itens.add(item);
    }

    public void removeItem(ItemOrcamento item) {
        this.itens.remove(item);
    }

    public String getObservacoes() {
        return observacoes;
    }

    public void setObservacoes(String observacoes) {
        this.observacoes = observacoes;
    }

    public SituacaoConsulta getSituacao() {
        return situacao;
    }

    public void setSituacao(SituacaoConsulta situacao) {
        this.situacao = situacao;
    }

    public String getMotivoReagendamento() {
        return motivoReagendamento;
    }

    public void setMotivoReagendamento(String motivoReagendamento) {
        this.motivoReagendamento = motivoReagendamento;
    }

    public String getMovitoCancelamento() {
        return movitoCancelamento;
    }

    public void setMovitoCancelamento(String movitoCancelamento) {
        this.movitoCancelamento = movitoCancelamento;
    }

    public List<FotoConsulta> getFotos() {
        return fotos;
    }

    public void setFotos(List<FotoConsulta> fotos) {
        this.fotos = fotos;
    }

    public void addFoto(FotoConsulta foto) {
        this.fotos.add(foto);
    }

    public void removerFoto(FotoConsulta foto) {
        for (int i = 0; i < this.fotos.size(); i++) {
            if (this.fotos.get(i).getFoto().equals(foto.getFoto())) {
                this.fotos.remove(i);
                break;
            }
        }
    }

    public Set<ItemOrcamento> getItensConcluidos() {
        return itensConcluidos;
    }

    public void setItensConcluidos(Set<ItemOrcamento> itensConcluidos) {
        this.itensConcluidos = itensConcluidos;
    }

    public void addItemConcluido(ItemOrcamento item) {
        this.itensConcluidos.add(item);
    }

    public void removeItemConcluido(ItemOrcamento item) {
        this.itensConcluidos.remove(item);
    }

}

编辑3: 好吧,我将我的dataTable更改为:

<p:dataTable rowKey="#{item.id}" var="item"
                            value="#{consultaMB.consulta.itensAsList}"

我在Consulta类中创建了方法“getItensAsList()”,一切正常。看:

 public List<ItemOrcamento> getItensAsList(){
        List<ItemOrcamento> itensAsList = new ArrayList<ItemOrcamento>();
        Iterator<ItemOrcamento> it = itens.iterator();
        while (it.hasNext())
            itensAsList.add(it.next());

        return itensAsList;
    }

我真的不知道dataTable只接受你的value属性中的“List”类型。

2 个答案:

答案 0 :(得分:0)

仅当您的对象仍处于托管状态时才会出现这种情况。

如果没有,首先必须将其合并以将其附加到持久化上下文,以便在使用getter时加载所有延迟属性。否则,您将在运行时遇到NullPointerException。

基本上只要您保留在交易中,您的对象就应该保持管理状态。如果你离开它然后尝试再次使用你的对象在另一个事务中(或不是),你必须合并它,以便它是最新的,如果另一个进程将它更新到你的数据库 - 或者你更新了这个对象的属性。 / p>

请参阅此答案中的架构,以获得生命周期的全局概述: How to know if a detached JPA entity has already been persisted or not?

答案 1 :(得分:0)

您引用的异常与延迟加载无关。您尚未使用必要的getter和setter方法在PersistentSet类中定义适当的字段ID。