Boa noite pessoas.
Depois de longos anos fora do mundo da programação Java, voltei a estudar com foco em um projeto de desenvolvimento web para o futuro.
Pois bem, estou tentando utilizar o Spring MVC 4, com JPA 2 e Hibernate 5 para controlar as transações com o banco de dados MySQL 8.
As conexões são todas realizadas, realizo consultas normalmente. O problema começa quando tento persistir, remover ou atualizar algum objeto, onde é necessário o controle de transação, e o Spring parece não estar fazendo essa injeção de dependência do EntityManager pra mim.
Segue os códigos:
dispatcher-servlet.xml
<!-- CONFIGURAÇÃO PARA ACEITAR ANOTAÇÕES -->
<mvc:annotation-driven />
<context:component-scan base-package="base" />
<!-- CONFIGURAÇÃO DE BEAN PARA O INTERCEPTOR DE LOGIN -->
<!--<mvc:interceptors>
<bean class="base.interceptors.LoginInterceptor" />
</mvc:interceptors>-->
<!-- CONFIGURAÇÃO DE BEAN PARA RESOLUÇÃO DAS VIEWS -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
applicationContext.xml
<!-- ATIVANDO AS TRANSAÇÕES VIA ANOTAÇÃO PELOS CONTROLLERS -->
<tx:annotation-driven transaction-manager="txManager" />
<bean id="mySQLDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/teste?useSSL=false&serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value="senha"></property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mySQLDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Classe Pessoa
package base.models;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "pessoas")
public class Pessoa {
@Id
@GeneratedValue
@Column(name = "id_pessoa", nullable = false)
private long id;
@Column(name = "nome_pessoa", nullable = false)
private String nome;
public Pessoa() {
}
public Pessoa(String nome) {
this.nome = nome;
}
public Pessoa(long id, String nome) {
this.id = id;
this.nome = nome;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
Classe JPAPessoaDAO
package base.hibernate;
import base.dao.interfaces.PessoaDAO;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import base.models.Pessoa;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceProperty;
import org.springframework.stereotype.Repository;
/*
A ANOTAÇÃO @REPOSITORY É UTILIZADA PARA A RESOLUÇÃO DE DEPENDÊNCIA DO DAO
*/
@Repository
public class JPAPessoaDAO implements PessoaDAO {
/*
Um PersistenceContext (Contexto Persistente) é um local onde ficam armazenados os objetos
(entidades) que estão sendo manipulados pelo EntityManager corrente
*/
@PersistenceContext
EntityManager manager;
@Override
public void inserirPessoa(Pessoa pessoa) {
manager.persist(pessoa);
}
@Override
public Pessoa buscarPessoa(long id) {
Pessoa pessoa = manager.find(Pessoa.class, id);
return pessoa;
}
@Override
public void removerPessoa(long id) {
Pessoa pessoa = manager.find(Pessoa.class, id);
manager.remove(pessoa);
}
@Override
public void atualizarPessoa(Pessoa pessoa) {
manager.merge(pessoa);
}
@Override
public List<Pessoa> listar() {
List<Pessoa> listaPessoas = manager
.createQuery("select p from Pessoa as p")
.getResultList();
return listaPessoas;
}
@Override
public List<Pessoa> listarPorID(long id) {
Query query = manager
.createQuery("select p from Pessoa as p where p.id = : paramID");
query.setParameter("paramID", id);
List<Pessoa> listaPessoas = query.getResultList();
return listaPessoas;
}
@Override
public EntityManager getEntityManager() {
return manager;
}
/*public static void main(String[] args) {
//JPAPessoaDAO pessoaDAO = new JPAPessoaDAO();
// INSERT
//Pessoa pessoa = new Pessoa("VALMORPE");
//pessoaDAO.inserirPessoa(pessoa);
// SELECT
//Pessoa pessoa = pessoaDAO.buscarPessoa(4L);
//System.out.println("Pessoa de ID 4: " + pessoa.getNome());
// DELETE
//pessoaDAO.removerPessoa(6);
// UPDATE
//Pessoa pessoa = new Pessoa(5L, "VALMIR");
//pessoaDAO.atualizarPessoa(pessoa);
// SELECT COM QUERY PRÓPRIA E WHERE RETORNANDO LISTA
//List<Pessoa> listaPessoas = pessoaDAO.listar();
//for (Pessoa pessoa : listaPessoas) {
//System.out.println("Pessoa de ID " + pessoa.getId() + " e nome " + pessoa.getNome());
//}
//
// SELECT COM QUERY PRÓPRIA, WHERE E RETORNANDO LISTA COM PARAMETRO
//List<Pessoa> listaPessoas = pessoaDAO.listarPorID(5L);
//for (Pessoa pessoa : listaPessoas) {
//System.out.println("Pessoa de ID " + pessoa.getId() + " e nome " + pessoa.getNome());
//}
}*/
}
Classe PessoaController
package base.controllers;
import base.dao.interfaces.PessoaDAO;
import base.models.Pessoa;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/*
A ANOTAÇÃO @TRANSACTIONAL INFORMA
*/
@Controller
public class PessoaController {
@Autowired
PessoaDAO pessoaDAO;
//Logger log = Logger.getLogger(PessoaDAO.class.getName());
@RequestMapping("lista-pessoas")
public String listarPessoas(Model model) throws InvocationTargetException {
//DebugUtils.transactionRequired("PessoaController.listarPessoas");
List<Pessoa> listaPessoas = pessoaDAO.listar();
model.addAttribute("listaPessoas", listaPessoas);
return "lista-pessoas";
}
@Transactional
@RequestMapping("add")
public String add(Model model) {
Pessoa pessoa = new Pessoa ("PESSOA TESTE");
pessoaDAO.inserirPessoa(pessoa);
//model.addAttribute("info", pessoaDAO.getEntityManager().isOpen());
model.addAttribute("info",
pessoaDAO.getEntityManager().isJoinedToTransaction());
return "add";
}
}
persistence.xml
<persistence-unit name="pessoas" transaction-type="RESOURCE_LOCAL">
<class>base.models.Pessoa</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>