Versiones comparadas

Clave

  • Se ha añadido esta línea.
  • Se ha eliminado esta línea.
  • El formato se ha cambiado.

...

Bloque de código
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.Oracle10gDialect
spring.jpa.generate-ddl = false
spring.jpa.hibernate.ddl-auto = validate


# Datasource
spring.datasource.url=jdbc:oracle:thin:@hydra-prescan.atica.um.es:1526/ZEUSDESA
spring.datasource.username=USUARIOBD
spring.datasource.password=CONTRASEÑABD

Entidades y DTOs

Una vez hayamos proporcionado a nuestra aplicación acceso a base de datos, debemos hacernos la clase java que mapee los objetos de base de datos que se van a obtener con el JpaRepository. Para auto generar las entidades, podemos consultar esta página de la wiki. También podemos generarlas a mano. Para ilustrar esto, tenemos la clase Usuario:

En nuestros backends Spring Boot, utilizamos el patrón DTO, con el que separamos los objetos de negocio de los objetos para transferencia de datos. Este último sería el DTO (Data Transfer Object) un objeto equivalente a las entidades (objetos de negocio) con los datos que queramos devolver, y sin las anotaciones que tiene la entidad (es un POJO), y a través del cuál también podemos obtener la entidad de base de datos. Devolver una entidad en un servicio no es una buena práctica, pues estos objetos pueden llevar información relacionada que no se debe trasnferir, y por ello es marcado como una vulnerabilidad en SonarQube, de ahí la necesidad de utilizar este patrón. 

Una vez hayamos proporcionado a nuestra aplicación acceso a base de datos, debemos hacernos la clase java que mapee los objetos de base de datos que se van a obtener con el JpaRepository. Para auto generar las entidades, podemos consultar esta documentación: Creación de Entidades JPA a partir de tablas de Base de Datos.

Para la conversión entre entidades y DTOs tenemos dos opciones que veremos en el siguiente sub-apartado, utilizar ModelMapper, o incluir tanto en la entidad como en el DTO un constructor que tome como parámetro el otro tipo. En el siguiente ejemplo se incluye ese constructor, y la entidad nos quedaría así:

Bloque de código
languagejava
package es.um.atica.--------;
 
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import es.um.atica..--------.UsuarioDTO;
 
@Entity
Bloque de código
languagejava
package es.um.atica.--------;
 
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import es.um.atica..--------.UsuarioDTO;
 
@Entity
@Table( name = "USUARIOS" )
public class Usuario {
 
    private String login;
 
    public Usuario() {
    }
 
    public Usuario(UsuarioDTO usuario) {
        this(usuario.getLogin());
    }
 
    public Usuario( String login ) {
        this.login = login;
    }
 
    //////////////////////////////////// GETTERS & SETTERS ////////////////////////////////////
    @Id
    public String getLogin() {
        return this.login;
    }
 
    public void setLogin( String login ) {
        this.login = login;
    }
}

Vemos Mientras que especificamos el nombre de la tabla. Tanto esto como los nombres de las columnas se pueden omitir si se corresponden con los nombres que tienen en base de datos, cambiando los guiones bajos por mayúsculas. Si en base de datos tenemos, por ejemplo, la columna USUARIO_ROL, nuestro atributo en Java lo llamaremos usuarioRol. Tenemos que incluir los getters y setters, poniendo en los get las anotaciones correspondientes, como @Id o @OneToMany, por poner ejemplos.

Nos puede llamar la atención UsuarioDTO. Los DTO, Data Transfer Objects, son clases simples, sin ninguna anotación; POJOs. Estos se utilizarán en los servicios REST para evitar vulnerabilidades al mandar objetos que van enlazados a entidades persistentes de base de datos. Aunque en los repositories no utilizaremos los DTOs, para que lo veamos con un ejemplo, UsuarioDTO sería así:

el DTO correspondiente sería este:

Bloque de código
languagejava
package es.um.atica..--------;
 
import es.um.atica.--------.Usuario;
 
public class UsuarioDTO {
 
    private String login;
 
    public UsuarioDTO() {
    }
 
    public UsuarioDTO(Usuario usuario) {
        this(usuario.getLogin());
    }
Bloque de código
languagejava
package es.um.atica..--------;
 
import es.um.atica.--------.Usuario;
 
public class UsuarioDTO {
 
    private String login;
 
    public UsuarioDTO() {
    }
 
    public UsuarioDTO(Usuario usuario) {
        this(usuario.getLogin());
    }
 
    public UsuarioDTO( String login ) {
        this.login = login;
    }
 
    //////////////////////////////////// GETTERS & SETTERS ///////////////////////////////////////
    public String getLogin() {
        return this.login;
    }
 
    public void setLogin( String login ) {
        this.login = login;
    }
 
}

Pasar listas de entidades a DTOs y viceversa

/
    public String getLogin() {
        return this.login;
    }
 
    public void setLogin( String login ) {
        this.login = login;
    }
 
}

Pasar listas de entidades a DTOs y viceversa

Como hemos visto, para pasar un solo objeto de entidad a DTO o viceversa disponemos del constructor correspondiente. Para todos los objetos de una lista a su otra forma, podríamos hacerlo con un for sin problemas, pero podemos hacerlo de una forma más simple utilizando expresiones lambda. A continuación tenemos un ejemplo con ambas formas de hacerlo, y podemos ver que el código queda más breve utilizando la expresión lambda:

Bloque de código
languagejava
		final List<AlumnoTitulacion> lista = alumnoTitulacionRepository.findAll();
		
		// Con un for
		final List<AlumnoTitulacionDTO> listaDTOfor = new ArrayList<AlumnoTitulacionDTO>();
		for(AlumnoTitulacion x : lista) {
			listaDTOfor.add( new AlumnoTitulacionDTO(x) );
		}
		
		// Con una expresión lambda
		final List<AlumnoTitulacionDTO> listaDTOlambda = lista.stream().map( x -> new AlumnoTitulacionDTO( x ) ).collect( Collectors.toList() );

Se pueden usar las dos formas indistintamente, según la forma que se prefiera.

ModelMapper

Una herrramienta que nos puede simplificar la conversión entre entidades y DTOs es ModelMapper. Es posible mapear los objetos complejos, es decir, los que tienen otros tipos anidados. Para utilizarlo, primero tenemos que declarar el bean en nuestro SecurityConfig.java, incluyendo la configuración de la estrategia de matching para que, como hemos dicho, se pueda hacer el mapeo complejo:

Bloque de código
languagejava
@Bean
public ModelMapper modelMapper() {
	final ModelMapper modelMapper = new ModelMapper();
	modelMapper.getConfiguration().setMatchingStrategy( MatchingStrategies.LOOSE );
	return modelMapper;
}

Para utilizarlo en nuestros servicios, simplemente tendremos que instanciarlo con Autowired:

Bloque de código
languagejava
@Autowired
private ModelMapper modelMapper;

El uso básico que haremos de éste será la conversión, para la que utilizaremos el método map, indicando el objeto a transformar y la clase destinoComo hemos visto, para pasar un solo objeto de entidad a DTO o viceversa disponemos del constructor correspondiente. Para todos los objetos de una lista a su otra forma, podríamos hacerlo con un for sin problemas, pero podemos hacerlo de una forma más simple utilizando expresiones lambda. A continuación tenemos un ejemplo con ambas formas de hacerlo, y podemos ver que el código queda más breve utilizando la expresión lambda:

Bloque de código
languagejava
		final List<AlumnoTitulacion>Diploma listadiploma = alumnoTitulacionRepository.findAll diplomaRepository.findById( 1 ).get();
final DiplomaDTO diplomaDto = modelMapper.map( diploma, DiplomaDTO.class );

Esto lo podemos utilizar con listas de la misma forma que hemos explicado previamente, con expresiones lambda o sin ellas:

Bloque de código
languagejava
final List<Diploma> lista = diplomaRepository.findAll();
final List<DiplomaDTO> listaDTO		
		// Con un for
		final List<AlumnoTitulacionDTO> listaDTOfor = new ArrayList<AlumnoTitulacionDTO>();
		for(AlumnoTitulacion x : lista) {
			listaDTOfor.add( new AlumnoTitulacionDTO(x) );
		}
		
		// Con una expresión lambda
		final List<AlumnoTitulacionDTO> listaDTOlambda = lista.stream().map( x -> new AlumnoTitulacionDTOmodelMapper.map( x, DiplomaDTO.class ) ).collect( Collectors.toList() );

...

Secuencias de base de datos

...