Spring boot + Spring JDBC


En este post se explicará como acceder a una base de datos con Spring boot utilizando Spring JDBC paso a paso. Para esto se utilizará como base el proyecto Spring Boot + REST Jersey Parte 1.

Paso 1 :  Configurar las dependencias necesarias

El primer paso es agregar las dependencias necesarias para el proyecto, en este caso se necesitarán 2 spring-boot-starter-jdbc y mysql-connector-java.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>
  • spring-boot-starter-jdbc : Contiene todas las clases necesarias para utilizar spring jdbc.
  • mysql-connector-java: Es el driver de mysql para Java que permitirá conectarnos vía jdbc.

Paso 2: Crear las tablas a utilizar en la base de datos

Para este ejemplo se utilizará como base de datos mysql para esto se creará una base de datos llamada jdbc_example con la siguiente estructura:

CREATE TABLE USER(
USER_ID INTEGER PRIMARY KEY AUTO_INCREMENT,
USERNAME VARCHAR(100) NOT NULL,
PASSWORD VARCHAR(100) NOT NULL
);

Con los siguientes datos:

INSERT INTO USER (USERNAME,PASSWORD)VALUES('raidentrance','superSecret');
INSERT INTO USER (USERNAME,PASSWORD)VALUES('john','smith');
INSERT INTO USER (USERNAME,PASSWORD)VALUES('juan','hola123');

Paso 3: Crear clase para representar el User

Ahora es necesario crear POJOS que representen los registros en la base de datos para esto se creará la clase User.java.

/**
 *
 */
package com.raidentrance.model;

/**
 * @author raidentrance
 *
 */
public class User {
	private Integer id;
	private String user;
	private String password;

	public User() {
	}

	public User(Integer id, String user, String password) {
		super();
		this.id = id;
		this.user = user;
		this.password = password;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}

Paso 4: Agregar la configuración de la base de datos al proyecto

El siguiente paso es incluir la configuración de la base de datos al proyecto, para esto es necesario editar el archivo application.properties con la siguiente configuración:

spring.datasource.url=jdbc:mysql://localhost:3306/jdbc_example
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

Paso 5: Crear un DAO(Data access object)

Una vez que Spring conoce los datos de conexión, el siguiente paso es crear un DAO el cuál nos servirá para ejecutar todas las acciones sobre la base de datos.

/**
 *
 */
package com.raidentrance.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.ws.rs.core.Response.Status;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import com.raidentrance.model.ServiceException;
import com.raidentrance.model.User;

/**
 * @author raidentrance
 *
 */
@Component
public class UserDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	public List<User> findAll() {
		List<User> users = jdbcTemplate.query("select * from user", new RowMapper<User>() {
			@Override
			public User mapRow(ResultSet rs, int arg1) throws SQLException {
				User user = new User(rs.getInt("USER_ID"), rs.getString("USERNAME"), rs.getString("PASSWORD"));
				return user;
			}
		});
		return users;
	}

	public User findByUsername(String username) throws ServiceException {
		User user = jdbcTemplate.query(new PreparedStatementCreator() {

			@Override
			public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
				PreparedStatement ps = con.prepareStatement("select * from user where username=?");
				ps.setString(1, username);
				return ps;
			}
		}, new ResultSetExtractor<User>() {
			@Override
			public User extractData(ResultSet rs) throws SQLException, DataAccessException {
				if (rs.next()) {
					User user = new User(rs.getInt("USER_ID"), rs.getString("USERNAME"), rs.getString("PASSWORD"));
					return user;
				} else {
					return null;
				}
			}
		});
		if (user != null) {
			return user;
		} else {
			throw new ServiceException(Status.NOT_FOUND.getStatusCode(), "User not found ", 4004);
		}
	}
}

En el código anterior se pueden observar los siguientes puntos importantes:

  • La anotación @Component : Significa que tendremos un objeto de esa clase viviendo dentro del contexto de Spring y que no será necesario utilizar el operador new para crearlo.
  • @Autowired JdbcTemplate jdbcTemplate : Indica que utilizando las configuraciones que se definieron en el archivo application.properties se creará un template de la clase JdbcTemplate(El cual es parte de spring data) y se inyectará en la referencia jdbcTemplate para que lo utilicemos.

  • public List findAll() : Este método será utilizado para buscar todos los usuarios que se encuentren en la tabla. Como se puede observar este objeto recibe el query que se desea ejecutar y un objeto del tipo RowMapper el cual define como se va a traducir de un ResultSet a un objeto Java de tipo User.

  • public User findByUsername(String username): Del mismo modo el método findByUsername será utilizado para buscar en la base de datos al usuario que tiene el username especificado. En este ejemplo se puede apreciar que se utiliza un PreparedStatement para prevenir SQL injection debido a que esta consulta recibe parámetros. Otro punto diferente es que a diferencia del método findAll() este utiliza un ResultSetExtractor en lugar de un RowMapper debido a que solo se espera un resultado en la repuesta.

  • Por último podemos ver que en caso de que no se encuentre el usuario se arrojará una excepción de tipo ServiceException con el mensaje, código y estatus http.

Paso 6: Utilizar el DAO en nuestro servicio

Una vez que ya se creo el DAO el siguiente paso es utilizarlo en nuestro endpoint, en futuros posts se verá que es mejor separarlo en servicios pero por ahora se inyectará en el endpoint UserResource.

/**
 *
 */
package com.raidentrance.resource;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.raidentrance.dao.UserDao;
import com.raidentrance.model.ServiceException;

/**
 * @author raidentrance
 *
 */

@Component
@Path("/users")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class UserResource {

	@Autowired
	private UserDao userDao;

	private static final Logger log = LoggerFactory.getLogger(UserResource.class);

	@GET
	public Response getUsers() {
		log.info("Getting users");
		return Response.ok(userDao.findAll()).build();
	}

	@GET
	@Path("/user/{username}")
	public Response getUser(@PathParam("username")String username) throws ServiceException {
		log.info("Getting users");
		return Response.ok(userDao.findByUsername(username)).build();
	}

}

Como se puede observar para inyectar el objeto de tipo UserDao lo único que se debe hacer es utilizar la anotación @Autowired ya que el objeto ya vive dentro del contexto de Spring.

Paso 7: Probando todo junto

Para ejecutar la aplicación se debe ejecutar la clase principal del mismo modo que en cualquier aplicación spring boot y se accederá a la siguiente url http://localhost:8080/users la cual mostrará lo siguiente:

Captura de pantalla 2017-09-18 a las 2.20.01 p.m.

Y para obtener solo un usuario se utilizará la url http://localhost:8080/users/user/raidentrance con la siguiente salida:

Captura de pantalla 2017-09-18 a las 2.21.40 p.m.

El código completo lo puedes encontrar en https://github.com/raidentrance/spring-boot-example/tree/part6-spring-jdbc.

Si quieres aprender más sobre web services o Spring boot recomendamos los siguientes libros:

Autor: Alejandro Agapito Bautista

Twitter: @raidentrance

Contacto:raidentrance@gmail.com

 

Anuncios

1 comentario »

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s