Hiberntate + Gravar imagem no banco + Out of Memory Java Heape

2 respostas
N

Bom dia!
Estou com um problema sério e não estou conseguindo resolver!

O objetivo do meu sistema é gravar fotos de cliente no banco de dados(Postgres 8.4)

Tenho duas classe Pessoa e Pessoa Fotos!

1 pessoa pode ter mais que uma FOTO

Segue as classes

PESSOA

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.Fetch;
/**
 *
 * @author  Nilodp
 */
@Entity
@Table(name = "PESSOA")
//@Inheritance(strategy = InheritanceType.JOINED)
@SequenceGenerator(name = "sequencia_pessoa", sequenceName = "sequencia_pessoa", initialValue = 1, allocationSize = 1)
public class Pessoa implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequencia_pessoa")
    private Long id;
    @Column(name = "DTNASC")
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dtNasc;
    @Column(name = "CPF", length = 20)
    private String cpf;
    @Column(name = "RG", length = 14)
    private String rg;
    @Column(name = "NOME", length = 60)
    private String nome;
    @Column(name = "SEXO", length = 1)
    private String sexo;
    @Column(name = "ENDERECO", length = 50)
    private String endereco;
    @Column(name = "NRO", length = 10)
    private String nro;
    @Column(name = "COMPLEMENTO", length = 60)
    private String complemento;
    @Column(name = "CEP", length = 12)
    private String cep;
    @JoinColumn(name = "CIDADE_ID", referencedColumnName = "ID")
    @ManyToOne(targetEntity = Cidade.class)
    private Cidade cidade;
    @Column(name = "BAIRRO", length = 60)
    private String bairro;
    @Column(name = "FONE_FIXO", length = 14)
    private String foneFixo;
    @Column(name = "FONE_MOVEL", length = 14)
    private String foneMovel;
    @Column(name = "EMAIL", length = 150)
    private String email;
    @Column(name = "PROFISSAO", length = 150)
    private String profissao;
    @Column(name = "OBSERVACAO", length = 700)
    private String observacao;
    @Column(name = "DH_CADASTRO")
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dhCadastro;
    @Column(name = "DH_ULT_ALTERACAO")
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dhUltAlteracao;
    @Column(name = "INATIVO", length = 1)
    private String inativo;  
    [b]@OneToMany(mappedBy="pessoa", fetch = FetchType.EAGER)
    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    @Fetch(org.hibernate.annotations.FetchMode.SELECT)
    private List<PessoaFotos> pessoasFotos = new ArrayList<PessoaFotos>();[/b]
    /*Anamnese*/

PESSOAFOTOS

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

/**
 *
 * @author Danilo
 */
@Entity
@Table(name = "PESSOAFOTOS")
@SequenceGenerator(name = "sequencia_foto", sequenceName = "sequencia_foto", initialValue = 1, allocationSize = 1)
public class PessoaFotos implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequencia_foto")
    private Long id;
    @ManyToOne(targetEntity = Pessoa.class, fetch=FetchType.LAZY)
    @Fetch(FetchMode.JOIN)
    @JoinColumn(name="pessoa_id")
    private Pessoa pessoa;    
    @Column(name = "descricaofoto")
    private String descricaoFoto;
    private byte[]  foto;
    @Transient
    private Boolean visualizarFoto = new Boolean(false);

Bom vamos ao problema

As classes acima funciona perfeitamente!

O problema é que quando uma pessoa tem fotos com tamanhos GRANDES(3 ou 4 fotos de 2 megas cada) acontece o erro abaixo!

Ou quando eu tento excluir varias fotos ao mesmo tempo

Segue o código da EXCLUSÃO
[b]private void excluirFoto() {
        Object[] options = {"Sim", "Não"};
        int op = JOptionPane.showOptionDialog(this, "Confirma exclusão da(s) foto(s) selecionada(s)?", "Excluir?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
        if (op == JOptionPane.YES_OPTION) {
            try {
                /* O que ocorre é que uma lista não pode ser iterada e modificada ao mesmo tempo,
                quero dizer, você não pode alterar uma lista e depois chamar next() no Iterator.
                Isto porque o Iterator pode perder a consistência, repetindo o mesmo elemento ou pulando algum.
                Para resolver isso, você pode criar uma cópia da lista, e iterar esta cópia, enquanto faz as modificações na lista original:
                 *
                 */
                List list = pessoa.getPessoasFotos();
                Iterator i = new ArrayList(pessoa.getPessoasFotos()).iterator(); // cria o iterator a partir da cópia
                while (i.hasNext()) {
                    PessoaFotos itens = (PessoaFotos) i.next();
                    if (itens.getVisualizarFoto() == true) { //compara a copia com a condição especificado, caso verdadeiro eu removo da lista original
                        pessoa.getPessoasFotos().remove(itens);
                        //list.remove(itens);
                        controlePessoa.excluirFoto(itens);
                        //controlePessoa.excluirFotosPost(itens);
                    }
                }
                montaTabelaFotos(pessoa.getPessoasFotos());
                TabelaConsultaFotos.updateUI();
                list = null;
                i = null;
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(this, "Erro ao excluir a foto " + ex, "Erro", JOptionPane.ERROR_MESSAGE);
            }
        }
    }[/b]
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Exception occurred during event dispatching:
java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:2882)
        at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100)
        at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:572)
        at java.lang.StringBuilder.append(StringBuilder.java:203)
        at java.util.AbstractMap.toString(AbstractMap.java:492)
        at org.hibernate.pretty.Printer.toString(Printer.java:82)
        at org.hibernate.pretty.Printer.toString(Printer.java:113)
        at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:120)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
        at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
        at br.com.blackline.utils.HibernateUtility.commitTransaction(HibernateUtility.java:78)
        at br.com.blackline.dao.DaoHibernateGenerico.delete(DaoHibernateGenerico.java:35)
        at br.com.blackline.controle.ControlePessoa.excluirFoto(ControlePessoa.java:60)
        at br.com.blackline.formulario.cadastros.FormularioPessoa.excluirFoto(FormularioPessoa.java:3035)
        at br.com.blackline.formulario.cadastros.FormularioPessoa.botaoExcluirfotoActionPerformed(FormularioPessoa.java:1852)
        at br.com.blackline.formulario.cadastros.FormularioPessoa.access$2100(FormularioPessoa.java:39)
        at br.com.blackline.formulario.cadastros.FormularioPessoa$20.actionPerformed(FormularioPessoa.java:1259)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
        at java.awt.Component.processMouseEvent(Component.java:6263)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
        at java.awt.Component.processEvent(Component.java:6028)
        at java.awt.Container.processEvent(Container.java:2041)
        at java.awt.Component.dispatchEventImpl(Component.java:4630)
        at java.awt.Container.dispatchEventImpl(Container.java:2099)
        at java.awt.Component.dispatchEvent(Component.java:4460)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)

Então pessoal não sei oque esta causando esse erro!

Se é erro no mapiamento das classe pessoa com a pessoaFotos Usando o EAGER E O LAZY

Por favor alguém me ajude!

Obrigado!

2 Respostas

rdmardegam

Aparentemente a memoria da sua virtual machine acabou.

Tente aumentar o tamanho da memoria da VM.

Tente utilizar o fetch = FetchType.LAZY.

Realmente é necessario efetuar uma copia para iterar o objeto?

Tente efetuar essas pequenas mudanças e veja se funciona.

Abraço.

D

Aumente o heap space da sua JVM antes de tudo via:

-Xms256m -Xmx512m

Onde -Xms seria o espaço inicial de alocação de memória pela JVM e -Xmx o espaço máximo.

Criado 21 de maio de 2010
Ultima resposta 23 de mai. de 2010
Respostas 2
Participantes 3