Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Hibernate nao esta persistindo o caminho da imagem

Boa tarde,

quando vou tentar gravar o caminho da imagem no BD, nao acontece absolutamente nada, nenhum erro, ele cai no if

if(result.hasErrors()){
            return form(produto);
        }

segue meu form:

<form:form action="${s:mvcUrl('PC#gravar').build()}" method="post" commandName="produto" enctype="multipart/form-data">

<div>
            <label>Sumário</label>
            <input name="sumario" type="file" />
</div>

AppWebConfiguration:

@Bean
    public MultipartResolver multipartResolver(){
        return new StandardServletMultipartResolver();
    }

ServletSpringMvc:

@Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setMultipartConfig(new MultipartConfigElement(""));
    }

classe produto :

private String sumarioPath;

classe ProdutoController:

@RequestMapping(method=RequestMethod.POST)
    public ModelAndView gravar(MultipartFile sumario, @Valid Produto produto, BindingResult result, RedirectAttributes redirectAttributes){
        dao.gravar(produto);

        System.out.println(sumario.getOriginalFilename());

        if(result.hasErrors()){
            return form(produto);
        }



        redirectAttributes.addFlashAttribute("sucesso","produto cadastrodo com sucesso");
        return new ModelAndView("redirect:produtos");
    }

uma duvida no form o name está sumario mas o atributo na classe está sumarioPath como o Spring vai conseguir fazer o bind no produto?

no console sai apenas isso nao da erro algum:

Hibernate: insert into Produto (dataLancamento, descricao, paginas, sumarioPath, titulo) values (?, ?, ?, ?, ?)
Hibernate: insert into Produto_precos (Produto_id, tipo, valor) values (?, ?, ?)
Hibernate: insert into Produto_precos (Produto_id, tipo, valor) values (?, ?, ?)
Hibernate: insert into Produto_precos (Produto_id, tipo, valor) values (?, ?, ?)
batedeira_simples.JPG

obrigado.

7 respostas

Fala Gabriel, tudo bem ?

O Spring não vai fazer o bind do caminho da imagem, já que ele não vem do form. Você precisará salvar a imagem, pegar o caminho onde o recurso foi salvo, e inserir no objeto manualmente.

Você poderia contar com alguma classe específica pra realizar o trabalho de salvar a imagem e devolver o recurso. (Existe essa etapa no curso).

Algo como:


@RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(MultipartFile sumario, @Valid Produto produto, BindingResult result, RedirectAttributes redirectAttributes){

    //essa linha não deveria estar aqui, somente depois de ver os erros de validação
    //dao.gravar(produto);

    System.out.println(sumario.getOriginalFilename());

    if(result.hasErrors()){
        return form(produto);
    }

    String caminhoDoArquivo = FileSaver.save(sumario);      
    produto.setSumarioPath(caminhoDoArquivo);

    //Aqui persiste o produto
    dao.save(produto);

    redirectAttributes.addFlashAttribute("sucesso","produto cadastrodo com sucesso");
    return new ModelAndView("redirect:produtos");
}

Espero ter ajudado. Abraço!

Beleza Rafael e vc?

sim essa é a proxima parte, mas meu codigo acredito que esta com erro pois quando eu mando cadastrar ele cai nesse trecho:

if(result.hasErrors()){
            return form(produto);
        }

eu retorno para pagina o /produto/form como esta no if

no final do primeiro video o instrutor executa e ele é redirecionado para a pagina de Produtos /produto

estou tentando usar os metodos do resultpara ver se localizo o erro mas nao achei o metodo.

obrigado.

Opa Gabriel,

Então, se a execução chega ali dentro if significa que existe um erro de validação nas informações que foram enviadas do form. Não necessariamente é erro no código, já que ele executa e volta pro form (sem exception). Você tem que ver quais dados está enviando e quais validações está aplicando sobre eles. Você está validando o sumarioPath ? lembre que ele não vem do form, se tiver validação nele o Spring vai barrar e voltar pro form ..

Dê uma olhada nisso. Qualquer coisa poste aqui como está sua classe produto, ou seu validador de produto pra darmos uma olhada.

Abraço

Nós validamos no form pela linha <form:errors path="dataLancamento"/> certo?

nao estou validando isso nem no form nem no Validador:

    @Override
    public void validate(Object targer, Errors error) {
        ValidationUtils.rejectIfEmpty(error, "titulo", "field.required");
        ValidationUtils.rejectIfEmpty(error, "descricao", "field.required");

        Produto produto = (Produto) targer;
        if (produto.getPaginas() <= 0) {
            error.rejectValue("paginas", "field.required");

        }
    }
}

classe de produto

package br.com.casadocodigo.models;

import java.util.Calendar;
import java.util.List;

import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.springframework.format.annotation.DateTimeFormat;

@Entity
public class Produto {

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private String titulo;
    private String descricao; 
    private int paginas;

    public void setId(Integer id) {
        this.id = id;
    }

    @ElementCollection
    private List<Preco> precos;

    @DateTimeFormat(pattern="dd/mm/yyyy")
    private Calendar dataLancamento;

    private String sumarioPath;

    public Calendar getDataLancamento() {
        return dataLancamento;
    }
    public void setDataLancamento(Calendar dataLancamento) {
        this.dataLancamento = dataLancamento;
    }
    public List<Preco> getPrecos() {
        return precos;
    }
    public void setPrecos(List<Preco> precos) {
        this.precos = precos;
    }
    public Integer getId() {
        return id;
    }
    public String getTitulo() {
        return titulo;
    }
    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }
    public String getDescricao() {
        return descricao;
    }
    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
    public int getPaginas() {
        return paginas;
    }
    public void setPaginas(int paginas) {
        this.paginas = paginas;
    }

    @Override
    public String toString() {
        return "Produto: titulo= " + titulo + ", descricao= " + descricao + ", paginas= " + paginas + "";
    }
    public String getSumario() {
        return sumarioPath;
    }
    public void setSumario(String sumario) {
        this.sumarioPath = sumario;
    }
}

eu peguei um erro pelo result

[Field error in object 'produto' on field 'sumario': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@3ccddc67]; codes [typeMismatch.produto.sumario,typeMismatch.sumario,typeMismatch.java.lang.String,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [produto.sumario,sumario]; arguments []; default message [sumario]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.String' for property 'sumario'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [java.lang.String] for property 'sumario': no matching editors or conversion strategy found]]

veja se ajuda por favor

solução!

Fala Gabriel,

Agora deu pra ver o que está acontecendo. Os metodos get e set do seu atributo sumarioPath estão como getSumario() e setSumario(). Ai o Spring tenta fazer o bind do seu arquivo direto com seu objeto produto. Ele tenta pegar o arquivo e colocar no sumarioPath que é uma string, dando em erro de conversão (que tb é pego pelo BindingResult.hasErrors())

Mude o nome dos métodos para setSumatioPath() e getSumarioPath(), assim o Spring vai entender que tem que fazer o bind do arquivo com o MultipartFile sumario no controller e não direto dentro do seu arquivo, onde você precisa apenas de uma String.

Creio que isso já resolve. Abraço!

Nossa que falta de atenção.

muito obrigado Rafael.

Imagina, xD .. acontece