En este apartado vamos a ver el funcionamiento de la parte ORM del framework llamado Spring Boot
Un ORM facilita el trabajo de creación de aplicaciones de base de datos ya que prácticamente automatiza la persistencia y consulta de datos basándose para ello en el mapeo de las entidades en objetos y viceversa.
Esqueleto
El primer paso es descargar el esqueleto de proyecto desde aquí. En el archivo pom.xml
están definidas las siguientes dependencias
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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.ieselcaminas</groupId>
<artifactId>jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jpa</name>
<description>Proyecto demo para JPA</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.1.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.40.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-community-dialects -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-community-dialects</artifactId>
<version>6.4.1.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
spring-boot-starter-data-jpa
define que utilizamos la capa JPA de Spring (Java Persistent API)sqlite-jdbc
define la base de datos SQLitehibernate-community-dialects
se define que vamos a usar dialectos JDBC
La clase java que tiene el método main
es JpaApplication.java
Que contiene el siguiente código. Es común para todas las aplicaciones
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package org.ieselcaminas.jpa;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JpaApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
//En este método definimos nuestro propio código
@Override
public void run(String... args) {
}
}
SpringApplication.run(JpaApplication.class, args);
es quien inicia la aplicación SpringBoot
Propiedades
Debemos definir un archivo llamado application.properties
dentro de la carpeta resources
con el siguiente contenido:
1
2
3
spring.datasource.url=jdbc:sqlite:src/main/resources/customers.sqlite
spring.datasource.driver-class-name=org.sqlite.JDBC
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
spring.datasource.url=jdbc:sqlite:src/main/resources/customers.sqlite
define como base de datoscustomers.sqlite
dentro del directorioresources
spring.datasource.driver-class-name=org.sqlite.JDBC
define la claseJDBC
que se va a usarspring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
y aquí se define que, de todos los dialectos SQL propietarios o no, se va a usarorg.hibernate.community.dialect.SQLiteDialect
Base de datos
Creamos la base de datos SQLite y creamos la siguiente tabla:
1
2
3
4
5
CREATE TABLE customer (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL
);
Entidad
Al igual que hemos hecho en Repository Pattern hemos de definir las entidades como clases POJO.
Es necesario que las columnas de la base de datos tengan el mismo nombre que los atributos de la clase. Antes de cada camelCase se introduce un
_
y se pone en minúsculacamel_case
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
package org.ieselcaminas.jpa.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
protected Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return id + " - " + firstName + " - " + lastName;
}
}
Vemos que esta clase se anota con @Entity
para indicarle al framework que esta clase la debe tratar como una entidad que tiene persistencia en base de datos.
1
2
3
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
Estas anotaciones le indican a JPA que el atributo id
es la clave primaria y que el valor se genera automáticamente. Después cada atributo de la entidad se mapea en un campo en la base de datos.
Repositorio
El siguiente paso es crear CustomerRepository
1
2
3
4
5
6
7
8
package org.ieselcaminas.jpa.repository;
import org.ieselcaminas.jpa.entity.Customer;
import org.springframework.data.repository.CrudRepository;
public interface CustomerRepository extends CrudRepository<Customer, Long> {
}
Extiende CrudRepository
para poder realizar las operaciones CRUD <Customer, Long>
. Long
es el tipo de la clave primaria de la entidad Customer
.
De momento no nos hace falta definir métodos de acceso a datos porque CrudRepository
ya provee findById
que selecciona un elemento a partir su id
y findAll
que devuelve una lista de todos los elementos.
Vamos a probar el repositorio creando algunos Customer
. Primero hemos de crear un constructor para que Spring cree la clase customerRepository
por nosotros. Esto se denomina Dependency Injection
1
2
3
4
private final CustomerRepository customerRepository;
public JpaApplication(CustomerRepository customerRepository){
this.customerRepository = customerRepository;
}
Y ahora ya podemos crear algún Customer
y mostrar todos:
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
@Override
public void run(String... args) {
Customer c = new Customer("Pepe", "García");
//El repositorio es donde están todos los métodos que tratan con la base de datos.
//En este caso está haciendo un INSERT ya que el objecto es nuevo
this.customerRepository.save(c);
//Pero también puedeo modificar un registro
c.setFirstName("Juan");
this.customerRepository.save(c);
//Vamos a seleccionar el Customer con id 1
//Se escribe 1L porque es un dato escrito a mano de tipo long
Optional<Customer> clienteOp = this.customerRepository.findById(1L);
clienteOp.ifPresent(System.out::println);
//Si queremos acceder al objeto Customer
if (clienteOp.isPresent()){
c = clienteOp.get();
System.out.println(c);
}
//El método findAll devuelve todos los registros de la entidad asociada
this.customerRepository.findAll().forEach(System.out::println);
//En este código estamos guardando los datos en un Iterable que es lo que devuelven los métodos findAll
Iterable<Customer> l = this.customerRepository.findAll();
for (Customer customer : l) {
System.out.println(customer);
}
//Cuidado que si no existe el registro con ID 5, saltará una excepción
c = this.customerRepository.findById(5L).get();
this.customerRepository.delete(c);
}
Construcción de Consultas
En el repositorio se definen todas aquellas consultas que sean necesarias. Hay algunas consultas que ya están hechas. Las puedes consultar en org.springframework.data.repository.CrudRepository
.
En general, no hace falta escribir el cuerpo de las consultas SQL ya que lo hace Spring Boot automáticamente por nosotros a partir del nombre del método y los parámetros. Por ejemplo:
1
2
public List<Customer> findCustomersByFirstName(String firstName);
public Customer findCustomerByFirstNameAndLastName(String firstName, String lastName)
Si creamos el método findCustomersByFirstName(String firstName)
devolvería aquellos con dicho firstName
y findCustomerByFirstNameAndLastName
que coincida el firstName
y el lastName
.
Fijaos en la diferencia:
- Si empieza por
findCustomerBy
devuelve un únicoCustomer
- Si empieza por
findCustomersBy
(cons
) devuelve una lista deCustomer
Tienes el listado completo de Querys aquí.
Si la consulta que queremos hacer no se puede crear con el asistente, siempre se puede escribir a mano el SQL de la misma.
1
2
@Query("SELECT COUNT(c) FROM Customer c")
public int countAllRecords();
Notes
Vamos a implementar la funcionalidad de poder crear notas que se adjuntan a un cliente. Es decir, vamos a crear una relación 1:N
Primero creamos la tabla note
:
1
2
3
4
5
6
CREATE TABLE note (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"text" TEXT NOT NULL,
id_customer INTEGER,
CONSTRAINT note_customer_FK FOREIGN KEY (id_customer) REFERENCES customer(id)
);
Ahora creamos la entidad Note
:
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 org.ieselcaminas.jpa;
import jakarta.persistence.*;
@Entity
public class Note {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String text;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="id_customer")
private Customer customer;
protected Note() {}
public Note(String text, Customer customer) {
this.text = text;
this.customer = customer;
}
public Long getId() {
return id;
}
public String getText() {
return text;
}
public Customer getCustomer() {
return customer;
}
@Override
public String toString() {
return text;
}
}
Mediante …
1
2
3
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="customer_id")
private Customer customer;
.. estamos creando un relación M:1
, la columna se llamará customer_id
y la entidad relacionada es Customer
Y ahora vamos a ver la parte 1
, es decir, Customer
1
2
@OneToMany(mappedBy = "customer", fetch=FetchType.EAGER)
private List<Note> notes = new ArrayList<>;
En este caso le indicamos mappedBy = "customer"
donde customer
es el nombre del campo en la relación N
Ahora creamos los setters.
1
2
3
4
5
6
7
public List<Note> getNotes(){
return this.notes;
}
public void addNote(Note note){
this.notes.add(note);
}
Y generamos el repositorio para Note
1
2
3
4
5
6
7
8
9
10
11
package org.ieselcaminas.jpa.repository;
import org.ieselcaminas.jpa.entity.Note;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface NoteRepository extends CrudRepository<Note, Long> {
}
Y lo inyectamos en el constructor:
1
2
3
4
5
private final NoteRepository noteRepository;
public JpaApplication(CustomerRepository customerRepository, NoteRepository noteRepository){
this.customerRepository = customerRepository;
this.noteRepository = noteRepository;
}
Y ya podemos crear y consultar notas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public void run(String... args) {
//Creamos una nota
// 1º el cliente
Customer c = customerRepository.findById(1L).get();
//Y ahora la nota
Note n = new Note("Primera nota", c);
noteRepository.save(n);
Customer c2 = customerRepository.findById(2L).get();
n = new Note("Primera nota María", c2);
noteRepository.save(n);
customerRepository.findCustomersByFirstName("Pepe").forEach(System.out::println);
}
Controladores
Además de los repositorios es común crearse un controlador que haga de intermediario entre la base de datos y la entidad.
En el siguiente ejemplo tenemos un método en el controlador de Customer
que permite la creación de un Customer
desde la entrada estándar.
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 org.ieselcaminas.jpa.controller;
import org.ieselcaminas.jpa.entity.Customer;
import org.ieselcaminas.jpa.repository.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Scanner;
@Component
public class CustomerController {
private final CustomerRepository customerRepository;
public CustomerController(CustomerRepository customerRepository){
this.customerRepository = customerRepository;
}
public Customer createCustomer(){
String firstName, lastName;
Customer c;
Scanner sc = new Scanner(System.in);
System.out.println("Enter customer's first name:");
firstName = sc.nextLine();
System.out.println("Enter customer's last name:");
lastName = sc.nextLine();
c = new Customer(firstName, lastName);
customerRepository.save(c);
return c;
}
}
Y lo usamos en el programa principal JpaApplication
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
......
private final CustomerController customerController;
public JpaApplication(CustomerRepository customerRepository,
NoteRepository noteRepository, CustomerController customerController){
this.customerRepository = customerRepository;
this.noteRepository = noteRepository;
this.customerController = customerController;
}
.....
@Override
public void run(String... args) {
this.customerController.createCustomer();
this.customerRepository.findAll().forEach(System.out::println);
}
Banco
Vamos a crear una relación n:m
como la que vimos anteriormente entre cliente
y cuenta corriente
Archivo pom.xml
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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.ieselcaminas</groupId>
<artifactId>jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jpa</name>
<description>Proyecto demo para JPA</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Boot JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- SQLite JDBC -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.41.2.2</version>
</dependency>
<!-- Hibernate Community Dialects -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-community-dialects</artifactId>
<version>6.1.7.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE clientes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL
);
CREATE TABLE cuentas_corrientes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL,
cantidad REAL
);
CREATE TABLE cliente_cuenta (
cliente_id INTEGER NOT NULL,
cuenta_id INTEGER NOT NULL,
PRIMARY KEY (cliente_id, cuenta_id),
FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE CASCADE,
FOREIGN KEY (cuenta_id) REFERENCES cuentas_corrientes(id) ON DELETE CASCADE
);
Y application.properties
1
2
3
spring.datasource.url=jdbc:sqlite:src/main/resources/banco.sqlite
spring.datasource.driver-class-name=org.sqlite.JDBC
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
La entidad Cliente
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
package jpa;
import jakarta.persistence.*;
@Entity
// Se le puede indicar que el nombre de la tabla no es "cliente", nombre por defecto que es // igual al nombre la entidad (Cliente), sino "clientes"
@Table(name = "clientes")
public class Cliente {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 100)
private String nombre;
// Siempre un constructor por defecto
public Cliente() {
}
public Cliente(String nombre) {
this.nombre = nombre;
}
// Getters y Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
@Override
public String toString(){
return this.nombre;
}
}
Y la entidad CuentaCorriente
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
package jpa;
import jakarta.persistence.*;
import jpa.Cliente;
@Entity
// Se le puede indicar que el nombre de la tabla no es "cuenta_corriente", nombre por
// defecto que es igual al nombre la entidad (CuentaCorriente), sino "cuentas_corrientes"
@Table(name = "cuentas_corrientes")
public class CuentaCorriente {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 100)
private String nombre;
@Column(nullable = false)
private double cantidad;
//Siempre debe tener un constructor vacío
public CuentaCorriente() {
}
//Se pueden hacer tantos constructores como deseemos
public CuentaCorriente(String nombre) {
this.nombre = nombre;
}
// Getters y Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public double getCantidad() {
return cantidad;
}
public void setCantidad(double cantidad) {
this.cantidad = cantidad;
}
// Otros setters
public void ingresar(double cantidad){
if (cantidad > 0 )
this.cantidad += cantidad;
}
public void retirar(double cantidad){
if (cantidad > 0 )
this.cantidad -= cantidad;
}
@Override
public String toString(){
return this.nombre + " - " + this.cantidad;
}
}
Y ahora ya podemos crear la relación ` n:m `:
En la entidad Cliente
:
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
/**
* IMPORTANTE fetch = FetchType.EAGER. En caso contrario es FetchType.LAZY y da
* error porque no se inicializa la lista de cuentas
*/
@ManyToMany(fetch = FetchType.EAGER)
/*
En este caso le decimos:
- que la tabla se llama cliente_cuenta
- que mi columna id se llama en esa tabla cliente_id
- que la columna de la cuenta se llama cuenta_id en dicha tabla
*/
@JoinTable(
name = "cliente_cuenta",
joinColumns = @JoinColumn(name = "cliente_id"),
inverseJoinColumns = @JoinColumn(name = "cuenta_id")
)
// Inicializar siempre el Set
private Set<CuentaCorriente> cuentas = new HashSet<>();
// Demás código ....
public Set<CuentaCorriente> getCuentas() {
return this.cuentas;
}
public void setCuentas(Set<CuentaCorriente> cuentas) {
this.cuentas = cuentas;
}
// Se puede crear un método para añadir la entidad relacionada a la lista.
// En otro caso, habría que usar cliente.getCuentas().add(cuenta)
public void addCuenta(CuentaCorriente cuenta) {
this.cuentas.add(cuenta);
}
Y en la entidad CuentaCorriente
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Le decimos que, en la entidad Cliente, las cuentas se almacenan en el atributo con nombre cuentas
@ManyToMany(mappedBy = "cuentas", fetch = FetchType.EAGER)
//Hay que inicializar la lista siempre
private Set<Cliente> clientes = new HashSet<>();
// Demás código ....
public Set<Cliente> getClientes() {
return this.clientes;
}
public void setClientes(Set<Cliente> clientes) {
this.clientes = clientes;
}
// Se puede crear un método para añadir la entidad relacionada a la lista.
// En otro caso, habría que usar cuenta.getClientes().add(cliente)
public void addCliente(Cliente cliente){
this.clientes.add(cliente);
}
Los repositorios
1
2
3
4
5
package jpa;
import org.springframework.data.jpa.repository.JpaRepository;
interface ClienteRepository extends JpaRepository<Cliente, Long> {}
y
1
2
3
4
5
package jpa;
import org.springframework.data.jpa.repository.JpaRepository;
interface CuentaCorrienteRepository extends JpaRepository<CuentaCorriente, Long> {}
Y ahora ya podemos probarlo.
Vamos a hacerlo mediante un Servicio
. En un servicio vamos creando los métodos relacionados con una entidad y que no deban estar en el repositorio.
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
package jpa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Se pueden hacer tantos servicios como deseemos, pero siempre hemos de crear métodos relacionados
* en ellos.
*/
@Service
class ClienteService {
/*
La anotación @Autowired indica a Spring que nos "auto inyecte" esta clase, en este caso ClienteRepository y
CuentaCorrienteRepository.
De esta forma ya no es necesario inyectarlas en el constructor
*/
@Autowired
private ClienteRepository clienteRepository;
@Autowired
private CuentaCorrienteRepository cuentaCorrienteRepository;
public void crearClienteConCuenta(String nombreCliente, String nombreCuenta) {
Cliente cliente = new Cliente(nombreCliente);
CuentaCorriente cuenta = new CuentaCorriente();
cuenta.setNombre(nombreCuenta);
cliente.getCuentas().add(cuenta);
cuenta.getClientes().add(cliente);
cuentaCorrienteRepository.save(cuenta);
clienteRepository.save(cliente);
}
}
Y ahora en main
lo probamos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package jpa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JpaApplication implements CommandLineRunner {
private final ClienteService clienteService;
public JpaApplication(ClienteService clienteService) {
this.clienteService = clienteService;
}
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
//En este método definimos nuestro propio código
@Override
public void run(String... args) {
this.clienteService.crearClienteConCuenta("Mengano", "Cmengano");
}
}
Vamos a crear otro método que permita asociar una cuenta con varios clientes:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void crearCuentaConClientes(String nombreCuenta) {
CuentaCorriente cuenta = new CuentaCorriente();
cuenta.setNombre(nombreCuenta);
cuenta.setCantidad(100);
Cliente cliente1 = new Cliente("Cliente 1");
Cliente cliente2 = new Cliente("Cliente 2");
cliente1.getCuentas().add(cuenta); // o cliente1.addCuenta(cuenta);
cuenta.getClientes().add(cliente1); // o cuenta.addCliente(cliente);
cliente2.getCuentas().add(cuenta);
cuenta.getClientes().add(cliente2);
this.cuentaCorrienteRepository.save(cuenta);
this.clienteRepository.save(cliente1);
this.clienteRepository.save(cliente2);
}
y en main
1
2
3
4
@Override
public void run(String... args) {
this.clienteService.crearCuentaConClientes("CuentaConMásDeUnCliente");
}
Resumen
Los pasos para crear una aplicación con Spring boot son:
- definir las dependencias en el archivo
pom.xml
- crear las entidades donde se mapean los campos de la tabla con los atributos de la clase POJO
- crear los repositorios. Uno para cada entidad. Se puede ir definiendo los métodos conforme nos vayan haciendo falta.
- crear los controladores, donde crearemos métodos que usarán las entidades y los repositorios.
- crear la aplicación, según el ejemplo.