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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
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.
1 2 3 4 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> |
Y agregamos los datos de conexión en application.properties.
1 2 3 4 5 6 7 8 9 10 11 |
# 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
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
1 2 |
@Autowired private RepositoryArticle repositoryArticle; |
Con esta anotación autoconectamos con el repositorio de Articles.
Creamos el método getList()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@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; } |
- Se conecta al repositorio de Articles y extrae en un List todos los Articles.
- Recorremos el arreglo y lo cargamos en su respectivo domain.
- Al ejecutar http://localhost:8090/kanban/articulos
Clase ControllerColumn
Agregamos
1 2 |
@Autowired private RepositoryColumn repositoryColumn; |
Con esta anotación autoconectamos con el repositorio de Column.
Creamos el método getList()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@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; } |
- Se conecta al repositorio de Column y extrae en un List todos las columnas.
- Recorremos el arreglo y lo cargamos en su respectivo domain.
- Se extraen los Articles de cada columna y lo agrega a los articulos del dominio.
- 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:
1 |
url: "columnas", |
y en el método buildsKanban cambiamos la variable columns a:
1 |
var columns = data; |
En resources/templates duplicamos kanbanWeb.html. Le cambiamos el nombre a kanbanjpa.html. Cambiamos la referencia al script de kanban:
1 2 |
<!-- 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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