Fiz as alterações para usar Injeção de Dependências, a primeira vista, ok!
Exemplo do problema.
Vou até a listagem de contas. Na primeira vez, ok. Ele lista sem problemas. Se tentar recarregar a listagem de contas ele me lança uma exception dizendo que a conexão está fechada.
java.lang.RuntimeException: java.sql.SQLException: Connection is closed.
Converti meu projeto pra MySQL. Mas com HSQLDB também ocorria o problema.
ConnectionFactory
package br.com.caelum.contas;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
public class ConnectionFactory {
public Connection getConnection() throws SQLException {
System.out.println("conectando ...");
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new SQLException(e);
}
return DriverManager.getConnection("jdbc:mysql://localhost:3306/estudos_java","root", "root");
}
}
ContaDao
package br.com.caelum.contas.dao;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import br.com.caelum.contas.ConnectionFactory;
import br.com.caelum.contas.modelo.Conta;
import br.com.caelum.contas.modelo.TipoDaConta;
@Repository
public class ContaDAO {
private Connection connection;
@Autowired
public ContaDAO(DataSource ds) {
try {
this.connection = ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void adiciona(Conta conta) {
String sql = "insert into contas (descricao, paga, valor, tipo) values (?,?,?,?)";
PreparedStatement stmt;
try {
stmt = connection.prepareStatement(sql);
stmt.setString(1, conta.getDescricao());
stmt.setBoolean(2, conta.isPaga());
stmt.setDouble(3, conta.getValor());
stmt.setString(4, conta.getTipo().name());
stmt.execute();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void remove(Conta conta) {
if (conta.getId() == null) {
throw new IllegalStateException("Id da conta naoo deve ser nula.");
}
String sql = "delete from contas where id = ?";
PreparedStatement stmt;
try {
stmt = connection.prepareStatement(sql);
stmt.setLong(1, conta.getId());
stmt.execute();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void altera(Conta conta) {
String sql = "update contas set descricao = ?, paga = ?, dataPagamento = ?, tipo = ?, valor = ? where id = ?";
PreparedStatement stmt;
try {
stmt = connection.prepareStatement(sql);
stmt.setString(1, conta.getDescricao());
stmt.setBoolean(2, conta.isPaga());
stmt.setDate(3, conta.getDataPagamento() != null ? new Date(conta
.getDataPagamento().getTimeInMillis()) : null);
stmt.setString(4, conta.getTipo().name());
stmt.setDouble(5, conta.getValor());
stmt.setLong(6, conta.getId());
stmt.execute();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public List<Conta> lista() {
try {
List<Conta> contas = new ArrayList<Conta>();
PreparedStatement stmt = this.connection
.prepareStatement("select * from contas");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
// adiciona a conta na lista
contas.add(populaConta(rs));
}
rs.close();
stmt.close();
connection.close();
return contas;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public Conta buscaPorId(Long id) {
if (id == null) {
throw new IllegalStateException("Id da conta nao deve ser nula.");
}
try {
PreparedStatement stmt = this.connection
.prepareStatement("select * from contas where id = ?");
stmt.setLong(1, id);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
connection.close();
return populaConta(rs);
}
rs.close();
stmt.close();
connection.close();
return null;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void paga(Long id) {
if (id == null) {
throw new IllegalStateException("Id da conta nao deve ser nula.");
}
String sql = "update contas set paga = ?, dataPagamento = ? where id = ?";
PreparedStatement stmt;
try {
stmt = connection.prepareStatement(sql);
stmt.setBoolean(1, true);
stmt.setDate(2, new Date(Calendar.getInstance().getTimeInMillis()));
stmt.setLong(3, id);
stmt.execute();
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
private Conta populaConta(ResultSet rs) throws SQLException {
Conta conta = new Conta();
conta.setId(rs.getLong("id"));
conta.setDescricao(rs.getString("descricao"));
conta.setPaga(rs.getBoolean("paga"));
conta.setValor(rs.getDouble("valor"));
Date data = rs.getDate("dataPagamento");
if (data != null) {
Calendar dataPagamento = Calendar.getInstance();
dataPagamento.setTime(data);
conta.setDataPagamento(dataPagamento);
}
conta.setTipo(Enum.valueOf(TipoDaConta.class, rs.getString("tipo")));
return conta;
}
}
Conta
package br.com.caelum.contas;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.springframework.beans.factory.annotation.Autowired;
public class ConnectionFactory {
public Connection getConnection() throws SQLException {
System.out.println("conectando ...");
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new SQLException(e);
}
return DriverManager.getConnection("jdbc:mysql://localhost:3306/estudos_java","root", "root");
}
}
Conta
package br.com.caelum.contas.modelo;
import java.util.Calendar;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
public class Conta {
private Long id;
//@NotEmpty(message= "{conta.descricao.vazia}")
//@Size(min = 5, max = 500, message="{conta.descricao.size}")
// @NotNull(message="{conta.descricao.vazia}")
@NotEmpty(message="{conta.descricao.vazia}")
@Size(min=3, message="{conta.formulario.descricao}")
private String descricao;
private boolean paga;
private double valor;
@DateTimeFormat(pattern="dd/MM/yyyy")
private Calendar dataPagamento;
private TipoDaConta tipo;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public boolean isPaga() {
return paga;
}
public void setPaga(boolean paga) {
this.paga = paga;
}
public Calendar getDataPagamento() {
return dataPagamento;
}
public void setDataPagamento(Calendar dataPagamento) {
this.dataPagamento = dataPagamento;
}
public TipoDaConta getTipo() {
return tipo;
}
public void setTipo(TipoDaConta tipo) {
this.tipo = tipo;
}
public double getValor() {
return valor;
}
public void setValor(double valor) {
this.valor = valor;
}
}
ContaController
package br.com.caelum.contas.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import br.com.caelum.contas.dao.ContaDAO;
import br.com.caelum.contas.modelo.Conta;
@Controller
public class ContaController {
private ContaDAO contaDao;
@Autowired
public ContaController(ContaDAO contaDao) {
this.contaDao = contaDao;
}
@RequestMapping("/formulario-adiciona-conta")
public String formulario() {
return "conta/formulario";
}
@RequestMapping("/adiciona-conta")
public String adicionaConta(@Valid Conta conta, BindingResult result) {
if (!result.hasFieldErrors("descricao")) {
contaDao.adiciona(conta);
}
return "conta/formulario";
// Importante, se feito o redirect, a mensagem
// de erro não é exibida.
// return "redirect:/formulario-adiciona-conta";
}
@RequestMapping("/remove-conta")
public String removeConta(Conta conta) {
contaDao.remove(conta);
return "redirect:lista-contas";
}
@RequestMapping("/paga-conta")
public void finaliza(Long id, HttpServletResponse response) {
contaDao.paga(id);
response.setStatus(200);
}
@RequestMapping("/mostra-conta")
public String mostra(Long id, Model model) {
model.addAttribute("conta", contaDao.buscaPorId(id));
return "conta/mostra-conta";
}
@RequestMapping("/altera-conta")
public String altera(Conta conta) {
contaDao.altera(conta);
return "redirect:lista-contas";
}
@RequestMapping("/lista-contas")
public ModelAndView listaConta() {
List<Conta> contas = contaDao.lista();
ModelAndView mv = new ModelAndView("conta/lista-contas");
mv.addObject("contas", contas);
return mv;
}
/**
* Versão alternativa utilizando a classe MODEL ao invés da classe
* ModelAndView
*/
// @RequestMapping("/lista-conta")
// public String lista(Model mv) {
// ContaDao dao = new ContaDao();
// List<Conta> contas = dao.lista();
//
// mv.addAttribute("contas", contas);
// return "conta/lista";
// }
}package br.com.caelum.contas.controller;
import java.util.List;
@Controller
public class ContaController {
private ContaDAO contaDao;
@Autowired
public ContaController(ContaDAO contaDao) {
this.contaDao = contaDao;
}
@RequestMapping("/formulario-adiciona-conta")
public String formulario() {
return "conta/formulario";
}
@RequestMapping("/adiciona-conta")
public String adicionaConta(@Valid Conta conta, BindingResult result) {
if (!result.hasFieldErrors("descricao")) {
contaDao.adiciona(conta);
}
return "conta/formulario";
// Importante, se feito o redirect, a mensagem
// de erro não é exibida.
// return "redirect:/formulario-adiciona-conta";
}
@RequestMapping("/remove-conta")
public String removeConta(Conta conta) {
contaDao.remove(conta);
return "redirect:lista-contas";
}
@RequestMapping("/paga-conta")
public void finaliza(Long id, HttpServletResponse response) {
contaDao.paga(id);
response.setStatus(200);
}
@RequestMapping("/mostra-conta")
public String mostra(Long id, Model model) {
model.addAttribute("conta", contaDao.buscaPorId(id));
return "conta/mostra-conta";
}
@RequestMapping("/altera-conta")
public String altera(Conta conta) {
contaDao.altera(conta);
return "redirect:lista-contas";
}
@RequestMapping("/lista-contas")
public ModelAndView listaConta() {
List<Conta> contas = contaDao.lista();
ModelAndView mv = new ModelAndView("conta/lista-contas");
mv.addObject("contas", contas);
return mv;
}
/**
* Versão alternativa utilizando a classe MODEL ao invés da classe
* ModelAndView
*/
// @RequestMapping("/lista-conta")
// public String lista(Model mv) {
// ContaDao dao = new ContaDao();
// List<Conta> contas = dao.lista();
//
// mv.addAttribute("contas", contas);
// return "conta/lista";
// }
}
package br.com.caelum.contas.controller;
import java.util.List;
@Controller
public class ContaController {
private ContaDAO contaDao;
@Autowired
public ContaController(ContaDAO contaDao) {
this.contaDao = contaDao;
}
@RequestMapping("/formulario-adiciona-conta")
public String formulario() {
return "conta/formulario";
}
@RequestMapping("/adiciona-conta")
public String adicionaConta(@Valid Conta conta, BindingResult result) {
if (!result.hasFieldErrors("descricao")) {
contaDao.adiciona(conta);
}
return "conta/formulario";
// Importante, se feito o redirect, a mensagem
// de erro não é exibida.
// return "redirect:/formulario-adiciona-conta";
}
@RequestMapping("/remove-conta")
public String removeConta(Conta conta) {
contaDao.remove(conta);
return "redirect:lista-contas";
}
@RequestMapping("/paga-conta")
public void finaliza(Long id, HttpServletResponse response) {
contaDao.paga(id);
response.setStatus(200);
}
@RequestMapping("/mostra-conta")
public String mostra(Long id, Model model) {
model.addAttribute("conta", contaDao.buscaPorId(id));
return "conta/mostra-conta";
}
@RequestMapping("/altera-conta")
public String altera(Conta conta) {
contaDao.altera(conta);
return "redirect:lista-contas";
}
@RequestMapping("/lista-contas")
public ModelAndView listaConta() {
List<Conta> contas = contaDao.lista();
ModelAndView mv = new ModelAndView("conta/lista-contas");
mv.addObject("contas", contas);
return mv;
}
/**
* Versão alternativa utilizando a classe MODEL ao invés da classe
* ModelAndView
*/
// @RequestMapping("/lista-conta")
// public String lista(Model mv) {
// ContaDao dao = new ContaDao();
// List<Conta> contas = dao.lista();
//
// mv.addAttribute("contas", contas);
// return "conta/lista";
// }
}