Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
20
respostas

PERSISTIR SEM UTILIZAR HIBERNATE

@RequestMapping("/produtos")
    public String gravar(Produto produto){
        System.out.println(produto);
        produtoDao.gravar(produto);
        return "/produtos/ok";
    }

Vocês utilizam este código para enviar os dados do formulário para a DAO. Gostaria de saber como pego os dados do formulário sem utilizar o Hibernate para pesistir no banco. Criei uma conexão com o SQL server, mas estou com dificuldades para saber como pegar os dados do formulário.

Para pegar utilizando Servlet usamos o HttpServletRequest.

20 respostas

Boa noite Daniel,

Você pode pegar os dados do formulário usando o HttpServletRequest. Ela é subinterface de ServletRequest, que contém o método getParameter(String param).

O Hibernate na verdade você usaria para, tendo já os dados vindos do teu formulário, persistí-los no SQL Server. Como você está criando a conexão na mão, pode persistir os dados manualmente, ou seja, via JDBC, usando o driver do SQL Server, escrevendo os inserts manualmente, abrindo conexão à base, executando a operação e fechando a conexão.

Espero ter ajudado. Qualquer dúvida, avisa aí.

Abraço,

Rafael.

Rafael, boa noite!

Obrigado pela resposta. Então acabei fazendo dessa forma utilizando a sub interface do ServletRequest e consequentemente o getParameter.

Eu estava pensando que daria para pegar esses dados do formulário da mesmo forma que é mostrado em aula ou de uma outra forma. Eu fiquei sem ação quando a aula chegou na parte de validar os dados do formulário, pqe eu acabei montando a aplicação de forma diferente do que é ministrado em aula. Então acabei abrindo a questão aqui o forum para ver se existia uma forma mais limpa de pegar os dados do formulário.

Rafael, vi esse exemplo e achei interessante, pois parece com o que foi passado no curso, porem não usa Hibernate. Veja se seria viável: http://www.codejava.net/frameworks/spring/spring-mvc-with-jdbctemplate-example

supondo que vc esteja usando um framework actionbasead que popule os objetos na requisição, quando vc faz:

@RequestMapping("/produtos")
    public String gravar(Produto produto){

        return "/produtos/ok";
    }

isso aqui não tem nada de Hibernate, me parece que é Spring que vc usa, então é só o Spring que popula os dados do produto com os dados oriundos do formulário, se não quiser usar hibernate, podes usar o Jdbctemplate que é um projeto da spring tbm, ou dar um jeito de injetar ou criar uma conexão jdbc normal e trabalhar com sql puro ou utilizar algum outro arcabouço jdbc como por exemplo o MyBatis que tbm tem uma integração legal com Spring

lendo mais atentamente, vejo que sseu problema não tem nada haver com hibernate e sim com o próprio spring. Vamos lá, se vc tem um produto e esse produto tem os atributos nome e preco por exemplo, quando vc submete o formulário, o próprio spring se encarrega de preencher o objeto produto.

<form:form  method="post"
                modelAttribute="produto" action="/produto">

<form:input path="name" type="text" 
                                id="nome"  />
<form:input path="preco" type="text" 
                                id="preco"  />

<button type="submit">enviar
                             </button>
</form:form>

usei tags do Spring, mas isso não importa, o importante é saber que ele vai usar o atributo name dos inputs, e vai tentar popular o objeto produto no momento do submit, então oque vc digitar no input com name="nome" ele vai tentar colocar dentro de produto.nome e assim por diante

``` @RequestMapping(value = "/produto", method = RequestMethod.POST) public String salvar(@ModelAttribute("produto") @Validated Produto produto){

Syso(produto.getNome);//o produto vai chegar aaqui carregado com os dados da requisição }

vc encontra um ótimo tutorial aqui:http://www.mkyong.com/spring-mvc/spring-mvc-form-handlingexample/

Oi Daniel,

Sim seria viável. É Spring usando JDBC. É outro modo de persistir seus dados em uma base.

As dicas do Ricardo parecem boas também. E o site do mkyong sempre tem bons exemplos. É uma ótima fonte.

Caso tenha mais duvidas, poste aí.

Caso tenha conseguido resolver o problema, pode por o post como solucionado? Assim, se mais alguém vir nossas mensagens, sabe que pode seguir o que conversamos aqui.

Abraço!

Ricardo, obrigado pela resposta. No meu formulário eu tenho um select de categorias de um produto que vem de uma entidade categoria. E na minha entidade produto eu tenho um atributo do tipo categoria. Seria viável fazer o formulário dessa forma com uma estrutura assim? Se você pode me responder seria importante pra que eu não perca muito tempo em uma questão que não que não é viável. Para pegar os dados eu uso o getParameter passo para as entidades e persisto no banco no momento funciona, mas queria ver outras formas fazer isso.

é viávél sim e muito comum também,amanhã pela manhã eu posto um código pra vc, sono tá brabo aqui

Oh agradeceria muito esse exemplo. Muito obrigado pela ajuda!!

Ricardo, boa tarde! Cara pesquisei e tentei fazer mais nunca da certo. Segue minha JSP, tentei fazer deixando apenas os atributos que vão direto para a entidade Produto. Porem não aparece nem o formulário de cadastro da erro logo na primeira linha onde tem o . O erro é :

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'produto' available as request attribute
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Mercadinho-JT - Cadastro de Produtos</title>
</head>
<body>
    <form:form id="formularioCadProdutos" action="/mercadinho-jt/produtos" method="POST" modelAttribute="produto">
        <div>
            <label>Código de Barras</label>
            <form:input type="text" id="codigoBarras" name="codigoBarras" path="codigoBarras"/>            
        </div>
        <div>
            <label>Nome Produto</label>
            <form:input type="text" id="nomeProduto" name="nomeProduto" path="nome"/>
        </div>
        <div>
            <label>Qunatidade</label>
            <form:input type="text" id="quantidade" name="quantidade" path="quantidade"/>
        </div>
        <div>
            <label>Número da Nota Fiscal</label>
            <form:input type="text" id="numeroNF" name="numeroNF" path="numeroNF"/>    
        </div>
        <div>
            <label>Preço de Compra</label>
            <form:input type="text" id="vlCompra" name="vlCompra" path="vlCompra"/>
        </div>
        <div>
            <label>Preço de Venda</label>
            <form:input type="text" id="vlVenda" name="vlVenda" path="vlVenda"/>
        </div>                
        <div>    
        <!-- MARCA É UMA ENTIDADE, E A ENTIDADE PRODUTO TEM UM ATIBUTO DO TIPO MARCA QUE RECEBE O CÓDIGO DA MARCA -->        
            <label>Marca Produto</label>
            <select id="marcaProduto" name="marcaProduto">
                <option value="">Selecione a Marca</option>
                <c:forEach items="${marcas }" var="marcas">
                    <option value="${marcas.idMarca }">${marcas.nome }</option>
                </c:forEach>                        
            </select>
        </div>    
        <div>        
        <!-- FORNECEDOR É UMA ENTIDADE, E A ENTIDADE PRODUTO TEM UM ATIBUTO DO TIPO FORNECEDOR QUE RECEBE O CÓDIGO DO FORNECEDOR -->
            <label>Forncedor</label>
            <select id="fornecedor" name="fornecedor">
                <option value="">Selecione o Fornecedor</option>
                <c:forEach items="${fornecedores }" var="fornecedor">
                    <option value="${fornecedor.id_Fornecedor }"> ${fornecedor.nome}</option>
                </c:forEach>    
            </select>    
        </div>            
        <div>
            <!-- CATEGÓRIA É UMA ENTIDADE, E A ENTIDADE PRODUTO TEM UM ATIBUTO DO TIPO CATEGÓRIA QUE RECEBE O CÓDIGO DA CATEGÓRIA -->
            <label>Categória do Produto</label>            
            <select id="categoria" name="categoria">
                <option value="">Selecione a Categória</option>
                <c:forEach items="${categorias }" var="categoria">
                    <option value="${categoria.id_Categoria }"> ${categoria.nome}</option>
                </c:forEach>    
            </select>    
        </div>            
        <button type="submit" id="btn-cadastrarProduto">Cadastrar Produto</button>
    </form:form>
</body>     
</html>

O meu Controller está assim:

@RequestMapping(method=RequestMethod.POST)
    public ModelAndView cadastrarProduto(@ModelAttribute("produto") @Validated Produto produto, BindingResult result, RedirectAttributes redirectAttributes){

        System.out.println(produto.getNome());
         if(result.hasErrors()){
                return executa();
            }
        //dao.create(produto);
        redirectAttributes.addFlashAttribute("sucesso","Produto Cadastrado Com Sucesso!!");
        return new ModelAndView("redirect:produtos");
    }

Como eu havia dito sobre a outra entidade que seria Categoria que possui na entidade Produto um atributo que uso para inserir na tabela produto no DB. Eu tenho outras duas entidades que possuem basicamente a mesma ideia onde tenho um <select que seleciono a opção e pego o código como esta demonstrado na pagina jsp. Se você puder me ajudar nessa questão, pois realmente não estou conseguindo fazer. Caso não seja possível irei ficar com a forma que já havia feito. Obrigado, agradeço desde já!!!

Boa galera!!!

Olá naquele exemplo que te passei tem como disponibilizar as listas para a view. 1- você deve colocar a lista no request, isso é feito na lógica que chama o formulario

    @RequestMapping(value = "/users/add", method = RequestMethod.GET)
    public ModelAndView showForm() {

        ModelAndView mv = new ModelAndView("/produto/formulario");
 //dao injetado com AutoWired
        List<Categoria> categorias = categoriaDao.findAll();
        mv.addAttribute("categorias", categorias);
        return mv;

    }

dessa forma essa coleção vai estar na requisição e vc vai poder iterar ela com jstl como vc fez la em cima

2-não misture a jstl com a taglib do spring, faz tudo com jstl mesmo

<form id="formularioCadProdutos" action="<c:url value="/mercadinho-jt/produtos"/"> method="POST">
        <div>
            <label>Código de Barras</label>
            <input type="text" id="codigoBarras" name="codigoBarras" />            
        </div>
        <div>
            <label>Nome Produto</label>
            <input type="text" id="nomeProduto" name="nomeProduto" />
        </div>
<!--continua o form-->
</form>

atenção, o nome dos atributos do Objeto devem coincidir com os names dos inputs, no exemplo é se se esperar que os atributos do produto sejam nomeProduto e codigoBarras

public class Produto(){

private String nomeProduto;
private String codigoBarras;
}

Preencho o <selec dessa forma:

@RequestMapping("form")
    public ModelAndView executa() throws SQLException{    

        List<Categoria> categorias = new PreencheListaComboDAO().preencheComboCategoria();
        List<Marca> marcas = new PreencheListaComboDAO().preencheComboMarcas();
        List<Fornecedor> fornecedores = new PreencheListaComboDAO().preencheComboFornecedor();

        ModelAndView modelAndView = new ModelAndView("produtos/form");    
        modelAndView.addObject("marcas", marcas);
        modelAndView.addObject("fornecedores", fornecedores);
        modelAndView.addObject("categorias", categorias);

        return modelAndView;
    }

Isso ai funciona tranquilo..

Então para pegar os dados hoje do formulário eu faço isso:

    @RequestMapping(method=RequestMethod.POST)
    public ModelAndView cadastrarProduto(HttpServletRequest req, HttpServletResponse resp, RedirectAttributes redirectAttributes) throws SQLException{
        produto = new Produto();
        produto = capturarFormularioProduto(req);    

        dao.create(produto);
        redirectAttributes.addFlashAttribute("sucesso","Produto Cadastrado Com Sucesso!!");
        return new ModelAndView("redirect:produtos");
    }
private Produto capturarFormularioProduto(HttpServletRequest req) {        
        produto = new Produto();

        Fornecedor fornecedor = new Fornecedor();
        Marca marca = new Marca();
        Categoria categoria = new Categoria();

        produto.setNome(req.getParameter("nomeProduto"));
        produto.setCodigoBarras(req.getParameter("codigoBarras"));
        produto.setNumeroNF(Integer.parseInt(req.getParameter("numeroNF")));
        produto.setQuantidade(Integer.parseInt(req.getParameter("quantidade")));

        marca.setIdMarca(Integer.parseInt(req.getParameter("marcaProduto")));
        fornecedor.setId_Fornecedor(Integer.parseInt(req.getParameter("fornecedor")));
        categoria.setId_Categoria(Integer.parseInt(req.getParameter("categoria")));

        produto.setForncedor(fornecedor);
        produto.setMarca(marca);
        produto.setCategoria(categoria);    

        return produto;
    }

O que gostaria de fazer é usar o exemplo que você deu para pegar esses dados do formulário sem ter que fazer esse código todo. Queria deixar essa captura mais elegante. Dessa forma que está funciona.

solução!

pois é Daniel, era pra funcionar

@RequestMapping(method=RequestMethod.POST)
    public ModelAndView cadastrarProduto(Produto produto) throws SQLException{

        dao.create(produto);
        redirectAttributes.addFlashAttribute("sucesso","Produto Cadastrado Com Sucesso!!");
        return new ModelAndView("redirect:produtos");
    }

a única coisa que notei é que alguns nomes de parametros que vem na requisição não coincidem com o nome dos campos do objeto produto, lembra se o produto tem um campo "nome", então o name do inputText tem que ser "nome", o teu problema certamente é esse

Ricardo, boa tarde! Cara quebrei a cabeça, mas consegui fazer como eu queria. Não sei se é uma "boa" prática, mas era assim que queria, O método ficou assim:

@RequestMapping(method=RequestMethod.POST)
    public ModelAndView cadastrarProduto(Produto produto, Preco preco, Marca marca, Fornecedor fornecedor, Categoria categoria, RedirectAttributes redirectAttributes) throws SQLException{

        produto.setMarca(marca);        
        produto.setPreco(preco);
        produto.setForncedor(fornecedor);
        produto.setCategoria(categoria);

        dao.create(produto);
        redirectAttributes.addFlashAttribute("sucesso","Produto Cadastrado Com Sucesso!!");
        return new ModelAndView("redirect:produtos");
    }

Peguei a dica que você deu a dei uma olhada em como estava as variáveis das entidades e deixei as names do form iguais. Também coloquei o método toString() nas entidades. Cara muito obrigado pelas dicas e boa vontade em ajudar. Agradeço muito, abraço!!!

Valeu Daniel, precisando é só perguntar!, só mais uma coisa pra completar, sim está correto, é a forma correta de se fazer sim,mas ainda dá pra melhorar, se produto tem um atributo marca do tipo Marca por exemplo, o atributo name do combobox poderia ficar

<select name="marca.id">

quando o spring submeter o form ele vai colocar o id da marca selecionada dentro de produto.marca.marcaId, fazendo assim para marca,preco,fornecedor e categoria, vc no exemplo acima só precisaria receber o produto e o redirectatributes pois o spring ia tratar de prhenncher o produto completo

Pohhhh! Valeu vou fazer isso, dessa forma fica muito melhor. Muito obrigado!! :D

Fiz a alteração e ficou bem melhor. Valeu pela dica. Abraços!!