SpringBoot 8. Kanban con JPA

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

 

SpringBoot 7. Crear modelo de la Base de Datos

Crear entitys de las tablas

Primero se debe verificar en la ventana Data Source Explorer que la conexión a las Base de Datos esta activa.

 

Clic derecho sobre el proyecto -> New -> Other… -> JPA -> JPA Entities from Tables.

JPA Entities from Tables

Seleccionar la conexión, el esquema y las tablas. También debemos asegurarnos que la opción List generated classes in persistence.xml este habilitado. En nuestro caso seleccionamos las tablas Article y Columns y clic en Next >.

Muestra la relaciones entre las tablas. Clic en Next.

En Key generador seleccionamos identity para que la llave que es numérica se incremente automáticamente. En el campo Package: de la sección Domain java class elegimos el paquete donde se generaran los entitys, en nuestro caso com.proyecto.model. Clic en Next >.

Aquí podemos editar cualquier campo de la tabla de forma individual desplegando la tabla y seleccionando el campo.

Lo recomendable es dejar todo como esta y clic en Finish.

Nos vamos al paquete de com.proyecto.model y podemos ver las clases entity que se generaron.

Descripción de entity

Los entity son JavaBean con anotaciones

  1. @Entity. Anotación que indica que es un entity
  2. @Table(name=”Columns”). Anotación que indica que hace referencia a la tabla correspondiente. Si  el entity se llama igual que la tabla no se muestra.
  3. @NamedQuery(name=»Column.findAll», query=»SELECT c FROM Column c»). Anotación que muestra los querys que podemos utilizar en la aplicación.
  4. @id. Id de la tabla
  5. @GeneratedValue(strategy=GenerationType.IDENTITY). Autoincrementa el id
  6. @OneToMany(mappedBy=»column»). Anotación que indica las relaciones con otras tablas.
  7. Cuenta con los métodos get y set como un JavaBean.

 

SpringBoot 6. Configurar JPA y la Base de Datos en Eclipse

Configurar JPA

En http://arieloliva.com/crearbasededatos/ creamos la Base de Datos Kanban. Vamos a conectar eclipse con está para habilitar JPA y crear los modelos.

Agregamos la dependencia JPA en el archivo pom.xml del proyecto.

	<dependency>
      		<groupId>org.springframework.boot</groupId>
      		<artifactId>spring-boot-starter-data-jpa</artifactId>
    	</dependency>

Después habilitamos JPA.

Clic derecho sobre el proyecto -> Propiedades -> Project Facets

Clic en Convert to faceted form…

Habilitar JPA con la versión 2.1. Clic en ApplyOK.

Crear conexión a MySQL

Para crear la conexión a MySQL,

Clic derecho sobre el proyecto -> Propiedades -> JPA -> Connection -> Add connection…

Seleccionar MySQL, elegir un nombre para la conexión y clic en Next.

Clic en el icono New Driver Definition  Elegir el driver 5.1.

Pasarse a la pestaña JAR List, seleccionar el driver mysql-connector-java-5.1.0-bin.jar y clic en Remove JAR/Zip para eliminarlo.

Selección_158
Clic en Add JAR/Zip… Ir a la ruta …/developer/db y seleccionar el archivo mysql-connector-java-5.1.41.jar (Se puede descargar de http://mvnrepository.com/artifact/mysql/mysql-connector-java/5.1.41 ). Clic en OK.

Escribir los datos de la Base de Datos MySQL.

Database kanban
URL jdbc:mysql://localhost:3306/kanban
User name root
Password El seleccionado en la instalación

Clic en Test Connection para validar que la conexión es correcta. Clic en OK.

Selección_161
Clic en Next >,  en Finish y en OK.

Validar la conexión a MySQL

Sobre Eclipse en la pestaña Data Source Explorer se muestra la conexión recién creada. Clic con el botón derecho y Connect.

Introducir la contraseña y OK.


Podemos ver las tablas de la Base de Datos de MySQL.

 

 

Java EE 6. Conectar Eclipse con MySQL

Configurar JPA

Clic con el botón derecho sobre el proyecto y seleccionar Propiedades. Clic en Project Facets. Asegurarse que este habilitado JPA y tiene seleccionado la versión 2.1.

Selección_154

Conectar con MySQL

En la misma ventana de propiedades, seleccionar JPA y en la sección de Connection clic en Add connection..
Selección_153
Seleccionar MySQL, elegir un nombre para la conección y clic en Next >.

Selección_155
Clic en el icono New Driver Definition.

Selección_156Elegir el driver 5.1.

Selección_157

Pasarse a la pestaña JAR List, seleccionar el driver mysql-connector-java-5.1.0-bin.jar y clic en Remove JAR/Zip para eliminarlo.

Selección_158
Clic en Add JAR/Zip... Ir a la ruta …/developer/db y seleccionar el archivo mysql-connector-java-5.1.38.jar (Se descargo el jar en el articulo http://arieloliva.com/configurar_proyecto/ en la sección «Dependencia para MySQL»). Clic en OK.

Selección_159
Escribir los datos de la Base de Datos MySQL.

Database mydb
URL jdbc:mysql://localhost:3306/mydb
User name root
Password El seleccionado en la instalación

Selección_160

Clic en Test Connection para validar que la conección es correcta.

Selección_161
Clic en Next > y  en Finish.

Validar la conección a MySQL

Sobre Eclipse en la pestaña Data Source Explorer se muestra la conección recién creada. Clic con el botón derecho y Connect.

Selección_163

Introducir la contraseña y OK.

Selección_164
Podemos ver las tablas de la Base de Datos de MySQL.

Selección_165