SpringBoot 8. Kanban con JPA

Contenido

Clase DatabaseConfig.java

Es necesario agregar las clase DatabaseConfig.java en el paquete com.proyecto.config para el acceso a la Base de Datos. Su contenido es:

package com.proyecto.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Contains database configurations.
 */
@Configuration
@EnableTransactionManagement
public class DatabaseConfig {

  // ------------------------
  // PUBLIC METHODS
  // ------------------------

  /**
   * DataSource definition for database connection. Settings are read from
   * the application.properties file (using the env object).
   */
  @Bean
  public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("db.driver"));
    dataSource.setUrl(env.getProperty("db.url"));
    dataSource.setUsername(env.getProperty("db.username"));
    dataSource.setPassword(env.getProperty("db.password"));
    return dataSource;
  }

  /**
   * Declare the JPA entity manager factory.
   */
  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    LocalContainerEntityManagerFactoryBean entityManagerFactory =
        new LocalContainerEntityManagerFactoryBean();
    
    entityManagerFactory.setDataSource(dataSource);
    
    // Classpath scanning of @Component, @Service, etc annotated class
    entityManagerFactory.setPackagesToScan(
        env.getProperty("entitymanager.packagesToScan"));
    
    // Vendor adapter
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
    
    // Hibernate properties
    Properties additionalProperties = new Properties();
    additionalProperties.put(
        "hibernate.dialect", 
        env.getProperty("hibernate.dialect"));
    additionalProperties.put(
        "hibernate.show_sql", 
        env.getProperty("hibernate.show_sql"));
    additionalProperties.put(
        "hibernate.hbm2ddl.auto", 
        env.getProperty("hibernate.hbm2ddl.auto"));
    entityManagerFactory.setJpaProperties(additionalProperties);
    
    return entityManagerFactory;
  }

  /**
   * Declare the transaction manager.
   */
  @Bean
  public JpaTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = 
        new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(
        entityManagerFactory.getObject());
    return transactionManager;
  }
  
  /**
   * PersistenceExceptionTranslationPostProcessor is a bean post processor
   * which adds an advisor to any bean annotated with Repository so that any
   * platform-specific exceptions are caught and then rethrown as one
   * Spring's unchecked data access exceptions (i.e. a subclass of 
   * DataAccessException).
   */
  @Bean
  public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
  }


  // ------------------------
  // PRIVATE FIELDS
  // ------------------------
  
  @Autowired
  private Environment env;

  @Autowired
  private DataSource dataSource;

  @Autowired
  private LocalContainerEntityManagerFactoryBean entityManagerFactory;


} // class DatabaseConfig

Agregamos la dependencia del conector mysql en el archivo pom.xml.

    	<dependency>
      		<groupId>mysql</groupId>
      		<artifactId>mysql-connector-java</artifactId>
    	</dependency>

Y agregamos los datos de conexión en application.properties.

# Database
db.driver: com.mysql.jdbc.Driver
db.url: jdbc:mysql://localhost:3306/kanban?zeroDateTimeBehavior=convertToNull
db.username: root
db.password: root

# Hibernate
hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql: true
hibernate.hbm2ddl.auto: update
entitymanager.packagesToScan:com.proyecto

Crear repositorios

Los repositorios (Repository) son interfaces que contienen los métodos necesarios para el acceso a Base de Datos.

Vamos a generar las clases RepositoryArticle y RepositoryColumn en el paquete com.proyecto.repository.

Clase RepositoryArticle:

package com.proyecto.repository;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.proyecto.model.Article;

@Repository
@Transactional
public class RepositoryArticle {

	public List<Article> getList(){
		return  entityManager.createQuery("from Article").getResultList();
	}
	
	@PersistenceContext
	private EntityManager entityManager; 

}

Clase RepositoryColumn:

package com.proyecto.repository;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.proyecto.model.Column;

@Repository
@Transactional
public class RepositorioColumn {

	public List<Column> getList(){
		return  entityManager.createQuery("from Column").getResultList();
	}
	
	@PersistenceContext
	private EntityManager entityManager; 

}

Crear dominios

Los dominios son clases que implementan los conceptos del problema que estamos resolviendo. En este caso es el modelado de las tablas Article y Column.

Vamos a generar las clases DomainArticle y DomainColumn en el paquete com.proyecto.domain.

Clase DomainArticle:

package com.proyecto.domain;

import java.io.Serializable;

import com.proyecto.model.Column;

public class DomainArticle implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id;
	private String descripcion;
	private String nombre;
	private String titulo;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getDescripcion() {
		return descripcion;
	}
	public void setDescripcion(String descripcion) {
		this.descripcion = descripcion;
	}
	public String getNombre() {
		return nombre;
	}
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}

}

Clase DomainColumn:

package com.proyecto.domain;

import java.io.Serializable;
import java.util.List;

public class DomainColumn implements Serializable {

	private static final long serialVersionUID = 1L;
	private int id;
	private String titulo;
	private List<DomainArticle> article;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTitulo() {
		return titulo;
	}
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}
	public List<DomainArticle> getArticle() {
		return article;
	}
	public void setArticle(List<DomainArticle> article) {
		this.article = article;
	}
	
}

Modificar Controller

Vamos a modificar los controller para accesar a los datos de las tablas correspondientes.

Clase ControllerArticle

Agregamos

@Autowired
private RepositoryArticle repositoryArticle;

Con esta anotación autoconectamos con el repositorio de Articles.

Creamos el método getList()

@RequestMapping(value="/articulos", method=RequestMethod.GET)
	@ResponseBody
	public List<DomainArticle> getList(){
		List<DomainArticle> articulos = new ArrayList<DomainArticle>();
		List<Article> listArticle = repositoryArticle.getList();
		for (Article article : listArticle) {
			DomainArticle domainArticle = new DomainArticle();
			domainArticle.setId(article.getId());
			domainArticle.setDescripcion(article.getDescripcion());
			domainArticle.setNombre(article.getNombre());
			domainArticle.setTitulo(article.getTitulo());
			
			articulos.add(domainArticle);
		}
		return articulos;
	}
  1. Se conecta al repositorio de Articles y extrae en un List todos los Articles.
  2. Recorremos el arreglo y lo cargamos en su respectivo domain.
  3. Al ejecutar http://localhost:8090/kanban/articulos

Clase ControllerColumn

Agregamos

@Autowired
private RepositoryColumn repositoryColumn;

Con esta anotación autoconectamos con el repositorio de Column.

Creamos el método getList()

@RequestMapping(value="/columnas", method=RequestMethod.GET)
	@ResponseBody
	public List<DomainColumn> getList(){
		List<DomainColumn> columnas = new ArrayList<DomainColumn>();
		List<Column> listColumn = repositoryColumn.getList();
		for (Column colum : listColumn) {
			DomainColumn domainColumn = new DomainColumn();
			domainColumn.setId(colum.getId());
			domainColumn.setTitulo(colum.getTitulo());
			
			List<DomainArticle> articulos = new ArrayList<DomainArticle>();
			for (Article articulo : colum.getArticles()) {
				DomainArticle domainArticle = new DomainArticle();
				domainArticle.setId(articulo.getId());
				domainArticle.setDescripcion(articulo.getDescripcion());
				domainArticle.setNombre(articulo.getNombre());
				domainArticle.setTitulo(articulo.getTitulo());
				articulos.add(domainArticle);
			}
			domainColumn.setArticle(articulos);
			columnas.add(domainColumn);
		}
		return columnas;
	}
  1. Se conecta al repositorio de Column y extrae en un List todos las columnas.
  2. Recorremos el arreglo y lo cargamos en su respectivo domain.
  3. Se extraen los Articles de cada columna y lo agrega a los articulos del dominio.
  4. Al ejecutar http://localhost:8090/kanban/columnas

 

Kanban con JPA

Nuevos archivos js y html

En resources/static/js duplicamos kanbanWeb.js. Le cambiamos el nombre a kanbanjpa.js. Cambiamos  la url a:

url:		"columnas",

y en el método buildsKanban cambiamos la variable columns a:

var columns = data;

En resources/templates duplicamos kanbanWeb.html. Le cambiamos el nombre a kanbanjpa.html. Cambiamos la referencia al script de kanban:

<!-- kanban  -->
<script type="text/javascript" src="js/kanbanjpa.js"	charset="UTF-8"></script>

Crear nuevo Controller

Creamos un nuevo controller en el paquete com.proyecto.controller llamado ControllerKanbanjpa.

package com.proyecto.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class ControllerKanbanjpa {
	@RequestMapping(value = "/jpa",method = RequestMethod.GET)
	public String index(){
		return "kanbanjpa";
	}
}

Al ejecutar http://localhost:8090/kanban/jpa. Tenemos las columnas y artículos de Kanban cargados desde la Base de Datos por medio de JPA.

Se puede descargar el proyecto completo de https://github.com/arielolivagh/kanbanjpa

 

Deja un comentario