Tutorial Spring REST 5/9 – Acceso a bases de datos SQL con Spring 4 y JPA

937

En este artículo revisaremos cómo configurar una conexión a bases de datos SQL mediante Hibernate y JPA en un proyecto de Spring 4 con Maven, en ordend de hacer nuestras conexiones a bases de datos, más rápidas y eficientes.

Configuración de Maven

Primeramente, agregaremos las dependencias de Spring Data y el conector de la base de datos que estemos utilizando, en este caso MySQL. Adicionalmente, agregamos el manejador de entidades de Hibernate y el pool de conexiones de Hikari.

	<!-- Spring Data -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-jdbc</artifactId>
	</dependency>
	<dependency>
	    <groupId>org.springframework.data</groupId>
	    <artifactId>spring-data-jpa</artifactId>
	</dependency>

	<!-- Hibernate -->
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-entitymanager</artifactId>
	</dependency>
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-validator</artifactId>
	</dependency>
	
	<!-- Hikari -->
	<dependency>
		<groupId>com.zaxxer</groupId>
		<artifactId>HikariCP</artifactId>
	</dependency>

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

Configuración de JPA

Para configurar una fuente de datos en nuestro proyecto, hablitaremos el manejo de transacciones, especificaremos el paquete donde se encontrarán nuestras entidades y repositorios JPA, especificaremos las credenciales de conexión y configuraremos los parámetros de Hibernate, como se muestra a continuación.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("org.codesolt.repository")
@PropertySource({ "classpath:persistance.properties" })
public class JDBCConfiguration {

	@Autowired
    private Environment env;
	
	@Bean
	public DataSource dataSource() {
		DriverManagerDataSource manager = new DriverManagerDataSource();
		manager.setDriverClassName(env.getProperty("jdbc.driver"));
		manager.setUrl(env.getProperty("jdbc.url"));
		manager.setUsername(EncodeUtil.decodeBase64String(env.getProperty("jdbc.user")));
		manager.setPassword(EncodeUtil.decodeBase64String(env.getProperty("jdbc.pass")));
		manager.setConnectionProperties(jpaProperties()); 	
		return manager;
	}
	
	 @Bean
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		 LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
	     em.setDataSource(dataSource());
	     em.setPackagesToScan(new String[] { "org.codesolt.model" });
	 
	     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
	     em.setJpaVendorAdapter(vendorAdapter);
	     em.setJpaProperties(jpaProperties());
	     
	     return em;
	}
	 
	@Bean
	public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
		JpaTransactionManager transactionManager = new JpaTransactionManager();
	    transactionManager.setEntityManagerFactory(emf);
	 
	    return transactionManager;
	}
	 
	@Bean
	public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
		return new PersistenceExceptionTranslationPostProcessor();
	}
	   
	@Bean
	public Properties jpaProperties() { 
		Properties jpaProperties = new Properties();
		jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
		jpaProperties.put("hibernate.hbm2ddl.auto", "validate");
		jpaProperties.put("hibernate.show_sql", "false");
		jpaProperties.put("hibernate.format_sql", "true");
		return jpaProperties;
	}
}

Entidades y repositorios JPA

Nuestras tablas en base de datos deberán estar mapeadas con un objeto en Java, en el cual especificarémos la tabla y las columnas, como se muestra a continuación (nota que se hace uso de anotaciones de diferentes bibliotecas de Java como Lombok o Hibernate Validator para la optimización del POJO).

@Entity
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@NoArgsConstructor
public class User {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer id;
	
	@NotNull
	@Size(min=1, max=100)
	private String userName;

	@Email
	@Size(min=1, max=100)
	private String email;
	
	@Size(min=1, max=100)
	private String password;
	
	@Size(min=1, max=100)
	private String role;
	
	@Min(0) @Max(1)
	private Integer active;
	
	@Column(name="CREATE_TS", updatable = false)
	private Date createTs;
	
	@Column(name="LAST_UPDT_TS", updatable = true)
	private Date lastUpdtTs;
	
	@PrePersist
	private void intialTs() {
		this.createTs = new Date();
		this.lastUpdtTs = new Date();
	}
	
	@PreUpdate
	private void updateTs() {
		this.lastUpdtTs = new Date();
	}
}

A continuación, configuramos nuestro repositorio JPA, el cual se encargará de realizar las operaciones CRUD a la entidad que especifiquemos, como se muestra a continuación (nota que no es necesario especificar los métodos, a excepción de cuando se requiera ejecutar un query específico).

@Repository
@Transactional
public interface UserRepository extends JpaRepository<User, Long> {
	
    Long deleteByUserName(String userName);

    @Query(value=
    	"SELECT u.id FROM User u WHERE u.userName = :userName")
    Integer findIdByUserName(@Param("userName") String userName);
}

Acceso a base de datos

Para consumir las interfaces de JPA definidas en nuestro proyecto, inyectarémos la interfáz requerida en la clase desde la que la consumiremos e inmediatamente harémos uso de sus métodos, como se muestra a continuación, en este caso para borrar registros.

public class UserManager {	
	
	@Autowired
	private UserRepository userRepo;
	
	public UserList deleteUser(String userName) {
		Instant start = Instant.now();
		UserList userList = new UserList();
		try {
			userRepo.deleteByUserName(userName);
			userList.setSuccess(true);
		} catch(Exception ex) {
			ex.printStackTrace();
			log.error(ex.toString());
			userList.setError(ex.toString());
			userList.setSuccess(false);
		}
		userList.setDuration(TimeUtil.formatDuration(Duration.between(start, Instant.now())));
		return userList;
	}

Al inyectar nuestro repositorio JPA en cualquier otra clase de nuestro proyecto, podremos acceder a los datos de nuestra base, con simplemente ejecutar los métodos que expone nuestro repositorio.

Continua con el tutorial

Recuerda que esta serie cuenta con 9 tutoriales, puedes consultar el siguiente sobre sobre Swagger 2 para documentar tus endpoints a continuación:

Tutorial Spring REST 6/9 – Configuración de Swagger 2 en Spring 4

Repositorio en Github

Nota que no todo el código del proyecto fue incluido en este artículo, puedes encontrar el código completo en nuestro repositorio de Github:

https://github.com/chuucks/SPRING-REST-API/

Recuerda darnos una estrellita ?


La configuración de Hibernate y JPA con Spring 4 mostrada en este artículo para un servicio REST, es solo una forma propuesta de hacerlo y tienen fines únicamente ilustrativos para nuestra la comunidad de Codesolt.

Comments

comments