Antes de empezar

1

Pasos para aprender Java Spring

2

驴Java sigue siendo gratuito?

3

Instalaci贸n de ambiente de desarrollo: Linux Ubuntu

4

Instalaci贸n de ambiente de desarrollo: macOS

5

Instalaci贸n de ambiente de desarrollo: Windows

Introducci贸n a Spring boot

6

驴Qu茅 es y qu茅 usaremos de Spring?

7

Conocer qu茅 es una aplicaci贸n autocontenida

8

Crear nuestra aplicaci贸n con Spring Initializr

9

Hola mundo con Spring Boot

10

Configurar Spring Boot

11

Crear la estructura del proyecto

Spring Data

12

驴Qu茅 es JPA?

13

Conocer qu茅 es Spring Data

14

Conectar la base de datos a nuestra aplicaci贸n

15

Mapear las tablas como clases

16

Crear Entity cuando su clave primaria es compuesta

17

Mapear relaciones entre clases

18

Usar la interface CrudRepository

19

Query Methods

Construyendo nuestra API

20

Implementar la anotaci贸n @Repository

21

驴Qu茅 es el patr贸n Data Mapper y qu茅 resuelve?

22

Orientar nuestra API al dominio con MapStruct

23

Orientar nuestro repositorio a t茅rminos del dominio

24

Inyecci贸n de dependencias

25

Implementar la anotaci贸n @Service

26

Implementar la anotaci贸n @RestController

27

Exponer nuestra API

Mejorando nuestra API

28

Controlar las respuestas HTTP

29

Crear el dominio de compras

30

Mapear el dominio de compras

31

Crear el repositorio de compras

32

Probando nuestros servicios de compras

33

Documentar nuestra API con Swagger

Spring Security

34

Configurar la seguridad de nuestra API con Spring Security

35

Generar un JWT

36

Autenticaci贸n con JWT

37

Autorizaci贸n con JWT

Despliegue de nuestra aplicaci贸n

38

Desplegar nuestra API desde la ventana de comandos

39

Desplegar nuestra base de datos con Heroku

40

Desplegar nuestra API con Heroku

41

Conclusiones y despedida del curso

A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Curso de Java Spring

Curso de Java Spring

Alejandro Ram铆rez

Alejandro Ram铆rez

Crear el repositorio de compras

31/41
Recursos

Aportes 29

Preguntas 7

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

@Service
public class PurchaseService {
    @Autowired
    private PurchaseRepository purchaseRepository;

    public List<Purchase> getAll() {
        return purchaseRepository.getAll();
    }

    public Optional<List<Purchase>> getByClient(String clientId) {
        return purchaseRepository.getByClient(clientId);
    }

    public Purchase save(Purchase purchase) {
        return purchaseRepository.save(purchase);
    }
}

@RestController
@RequestMapping("/purchases")
public class PurchaseController {
    @Autowired
    private PurchaseService purchaseService;

    @GetMapping("/all")
    public ResponseEntity<List<Purchase>> getAll() {
        return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
    }

    @GetMapping("/client/{idClient}")
    public ResponseEntity<List<Purchase>> getByClient(@PathVariable("idClient") String clientId) {
        return purchaseService.getByClient(clientId)
                .map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK))
                .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @PostMapping("/save")
    public ResponseEntity<Purchase> save(@RequestBody Purchase purchase) {
        return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.CREATED);
    }
}

Me parece que el video de esta clase esta diferente del audio

En mi caso la petici贸n de compras me sacaba error debido a que me indicaba que no era posible convertir el numero de celular por un entero, para esto tuve que cambiar el atributo celular de la entidad Cliente a Long y ya me funciono 馃槂

La verdad me parece muy bueno el curso, pero no se si soy solo yo o es que el hacer todo de un solo sin ir probando paso a paso hace qu猫 se m脿s complicado de entender.

Aveces es bueno ir mostrando los errores o que pasaria si tal anotacion no va o etc鈥 pero en general es bueno el curso.

es necesario el @mapsid, no es suficiente con el join column que ya especifca como se resuelve la relacion?

Consejo sano del curso: cada video compilen y corran su codigo.

A la hora de generar los controllers, y dar respuestas HTTP
Es buena pr谩ctica generar 2 posibles respuestas (Efectiva - Negativa) con Try Catch. As铆:

    @GetMapping("/")
    public ResponseEntity<List<Purchase>> getAll() {
        try {
            return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
        } catch (RuntimeException ex) {
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
    }

Algo as铆鈥
De esta manera nos estamos asegurando que en caso de no encontrar respuesta o encontrar respuestas sin contenido podamos manejar errores y mostrarlos en pantalla de una forma m谩s espec铆fica y controlada; si me equivoco por favor no duden en corregirme jajaj.

Alguien que me pueda explicar un poco m谩s a profundidad la annotation @MapsId
Gracias!!

Nombre la clase Purchase como Cart,pero el c贸digo es el mismo

import java.util.List;
import java.util.Optional;

import com.platzi.market.domain.dto.CartDTO;
import com.platzi.market.domain.respositories.CartRepositoryDTO;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CartService {

    @Autowired
    CartRepositoryDTO repo;

    public List<CartDTO> getAll() {
        return repo.getAll();
    }

    public Optional<List<CartDTO>> getByClient(int clent) {
        return repo.getByClient(clent);
    }

    public CartDTO save(CartDTO cart) {
        return repo.save(cart);
    }
}
package com.platzi.market.web.controller;

import java.util.List;
import java.util.Optional;

import com.platzi.market.domain.dto.CartDTO;
import com.platzi.market.domain.service.CartService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/cart")
public class CartController {
    @Autowired
    private CartService service;

    @GetMapping("/all")
    public List<CartDTO> getAll() {
        return service.getAll();
    }

    @GetMapping("/by_client/{client}")
    public Optional<List<CartDTO>> getByClient(@PathVariable("client") int client) {
        return service.getByClient(client);
    }

    @PostMapping("/add")
    public CartDTO save(CartDTO cart) {
        return service.save(cart);
    }

}

Orgulloso de que el ejercicio me saliera un 90% parecido al correcto, le err茅 en getByClient jaja

Se ha cruzado mi v铆deo. Lo informo por si le ocurre a otras personas y as铆 puedan arreglarlo.

package com.platzimarket.domain.service;

import com.platzimarket.domain.Purchase;
import com.platzimarket.domain.repository.PurchaseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class PurchaseService {

@Autowired
private PurchaseRepository purchaseRepository;

public List<Purchase> getAll(){
    return purchaseRepository.getAll();
}

public Optional<List<Purchase>> getByClient(String clientId){
    return purchaseRepository.getByClient(clientId);
}

public Purchase save(Purchase purchase) {
    return purchaseRepository.save(purchase);
}

}

package com.platzimarket.web.controller;

import com.platzimarket.domain.Purchase;
import com.platzimarket.domain.service.PurchaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController//Esto le indica a Spring que esta clase sera el controlador de una API Rest
@RequestMapping("/purchases")//Es el path en el que yo quiero que se hagan las peticiones
public class PurchaseController {
@Autowired
private PurchaseService purchaseService;

@GetMapping("/all")
public ResponseEntity<List<Purchase>> getAll(){
    return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
}

@GetMapping("/client/{idClient}")
public ResponseEntity<List<Purchase>> getByClient(@PathVariable("idClient") String clientId){
    return purchaseService.getByClient(clientId)
            .map(purchases -> new ResponseEntity<>(purchases,HttpStatus.OK))
            .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

@PostMapping("/save")
public ResponseEntity<Purchase> save(@RequestBody Purchase purchase) {
    return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.CREATED);
}

}

Comparto mi c贸digo del servicio y controlador.

@Service
public class PurchaseService {

    @Autowired
    private PurchaseRepository purchaseRepository;

    /**
     * Metodo para listar las compras.
     *
     * @return Lista de compras
     */
    public List<Purchase> getAll(){
        return purchaseRepository.getAll();
    }

    /**
     * Metodo para buscar las compras de un cliente
     *
     * @param clientId Identificador del cliente de tipo String
     * @return las compras del cliente
     */
    public Optional<List<Purchase>> getByClient(String clientId){
        return purchaseRepository.getByClient(clientId);
    }

    /**
     * Metodo para guardar una compra
     *
     * @param purchase Entity de Purchase
     * @return
     */
    public Purchase save(Purchase purchase){
        return purchaseRepository.save(purchase);
    }

}

@RestController
@RequestMapping(value = 鈥/purchases鈥)
public class PurchaseController {

@Autowired
private PurchaseService purchaseService;

@GetMapping(value = "/all")
public ResponseEntity<List<Purchase>> getAll(){
    return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
}

@GetMapping(value = "/{clientId}")
public ResponseEntity<List<Purchase>> getByClient(@PathVariable String clientId){
    return purchaseService.getByClient(clientId)
            .map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK))
            .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

@PostMapping(value = "/save")
public ResponseEntity<Purchase> save(@RequestBody Purchase purchase){
    return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.OK);
}

}```

Estuvo densa esta clase, me dejo un poco loco la cantidad de vueltas que se da con las relaciones entre las clases y las relaciones de los mapper y las entidades 馃樀鈥嶐煉.

Error: Could not read entity state from ResultSet EntityKey[] with root cause spring.

Causa: El celular de la entidad Cliente estaba como integer y lo cambie a long.

@Service
public class PurchaseService {
    @Autowired
    private PurchaseRepository purchaseRepository;

    public List<Purchase> getAll() {
        return purchaseRepository.getAll();
    }

    public Optional<List<Purchase>> getByClient(String clientId) {
        return purchaseRepository.getByClient(clientId);
    }

    public Purchase save(Purchase purchase) {
        return purchaseRepository.save(purchase);
    }
}
@RestController
@RequestMapping("/purchases")
public class PurchaseController {

    @Autowired
    private PurchaseService purchaseService;

    @GetMapping("/all")
    public ResponseEntity<List<Purchase>> getAll() {
        return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
    }

    @GetMapping("/client/{idClient}")
    public ResponseEntity<List<Purchase>> getByClient(@PathVariable("idClient") String clientId) {
        return purchaseService.getByClient(clientId).map(
                purchases -> new ResponseEntity<>(purchases, HttpStatus.OK)
        ).orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @PostMapping("/save")
    public ResponseEntity<Purchase> save(@RequestBody Purchase purchase) {
        return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.CREATED);
    }
}

Compa帽eros les comparto mi servicio de Purchase

package com.platzi.market.domain.service;

import com.platzi.market.domain.Purchase;
import com.platzi.market.domain.repository.PurchaseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class PurchaseService {

@Autowired
PurchaseRepository purchaseRepository;

public List<Purchase> getAll() {
    return purchaseRepository.getAll();
}

public Optional<Purchase> getPurchase(int purchaseId){
    return purchaseRepository.getPurchase(purchaseId);
}

public Optional<List<Purchase>> getByClient(String clientId){
    return  purchaseRepository.getByClient(clientId);
}

public Purchase save(Purchase purchase){
    return purchaseRepository.save(purchase);
}

}

Compa帽eros, les comparto mi c贸digo del controlador de Purchase

package com.platzi.market.web.controller;

import com.platzi.market.domain.Purchase;
import com.platzi.market.domain.service.PurchaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/purchases")
public class PurchaseController {

@Autowired
private PurchaseService purchaseService;

@GetMapping("/{purchaseId}")
public ResponseEntity<Purchase> getPurchase(@PathVariable("purchaseId") int purchaseId){
    return purchaseService.getPurchase(purchaseId)
            .map(purchase -> new ResponseEntity<>(purchase, HttpStatus.OK))
            .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

@GetMapping("/client/{clientId}")
public ResponseEntity<List<Purchase>> getByClient(@PathVariable("clientId") String clientId){
    return purchaseService.getByClient(clientId)
            .map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK))
            .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

@GetMapping("/save")
public ResponseEntity<Purchase> save(@RequestBody Purchase purchase){
    return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.OK);
}

}

Referente al reto:

PurchaseController

package com.platzi.market.web.controller;

import com.platzi.market.domain.Purchase;
import com.platzi.market.domain.service.PurchaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.function.Predicate;

import static org.springframework.http.HttpStatus.CREATED;
import static org.springframework.http.HttpStatus.NOT_FOUND;

@RestController
@RequestMapping("/purchases")
public class PurchaseController {
    private PurchaseService purchaseService;

    @Autowired
    public PurchaseController(PurchaseService purchaseService) {
        this.purchaseService = purchaseService;
    }

    @GetMapping
    public ResponseEntity<List<Purchase>> getAll() {
        return ResponseEntity.ok(purchaseService.getAll());
    }

    @GetMapping("/client/{id}")
    public ResponseEntity<List<Purchase>> getAllByClient(@PathVariable(value = "id") String clientId) {
        return purchaseService.getAllByClient(clientId)
                .filter(Predicate.not(List::isEmpty))
                .map(ResponseEntity::ok)
                .orElse(new ResponseEntity<>(NOT_FOUND));
    }

    @PostMapping
    public ResponseEntity<Purchase> save(@RequestBody Purchase purchase) {
        return new ResponseEntity<>(purchaseService.save(purchase), CREATED);
    }
}

PurchaseService

import java.util.List;
import java.util.Optional;

@Service
public class PurchaseService {
    private PurchaseRepository purchaseRepository;

    @Autowired
    public PurchaseService(PurchaseRepository purchaseRepository) {
        this.purchaseRepository = purchaseRepository;
    }

    public List<Purchase> getAll() {
        return purchaseRepository.getAll();
    }

    public Optional<List<Purchase>> getAllByClient(String clientId) {
        return purchaseRepository.getAllByClient(clientId);
    }

    public Purchase save(Purchase purchase) {
        return purchaseRepository.save(purchase);
    }
}

No me queda claro cuando se debe usar la etiqueta @MapsId. O con @JoinColumn es suficiente?

Me puediran ayudar con este erro que me sale cuando intento consultar mi purchase/all

Caused by: org.postgresql.util.PSQLException: ERROR: el operador no existe: character varying = integer

package com.platzi.market.domain.service;

import com.platzi.market.domain.Purchase;
import com.platzi.market.domain.repository.PurchaseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class PurchaseService {
    @Autowired
    private PurchaseRepository purchaseRepository;

    public List<Purchase> getAll(){
        return purchaseRepository.getAll();
    }

    public Optional<List<Purchase>> getByClient(String clientId){
        return purchaseRepository.getByClient(clientId);
    }

    public Purchase save(Purchase purchase){
        return purchaseRepository.save(purchase);
    }
}
package com.platzi.market.web.controller;

import com.platzi.market.domain.Purchase;
import com.platzi.market.domain.service.PurchaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.function.Predicate;

@RestController
@RequestMapping("/purchases")
public class PurchaseController {
    @Autowired
    private PurchaseService purchaseService;

    @GetMapping("/all")
    public ResponseEntity<List<Purchase>> getAll(){
        return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
    }

    @GetMapping("/purchase/{id}")
    public ResponseEntity<List<Purchase>> getByClient(@PathVariable("id") String clientId){
        return purchaseService.getByClient(clientId).filter(Predicate.not(List::isEmpty))
                .map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK))
                .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @PostMapping("/save")
    public ResponseEntity<Purchase> save(@RequestBody Purchase purchase){
        return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.CREATED);
    }

}

Hello guys, I鈥檓 going to to share how is going my project until now: https://github.com/borisbikes/platzi/tree/main/Spring/platzi-market
It鈥檚 implemented with Lombok and MapStruct

Integraci贸n en cascada

Espero que que este bien :p

  • PurchaseService.java
package com.cesar1e.market.domain.service;

import com.cesar1e.market.domain.Purchase;
import com.cesar1e.market.domain.repository.PurchaseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class PurchaseService {
    @Autowired
    private PurchaseRepository purchaseRepository;

    public List<Purchase> getAll(){
        return purchaseRepository.getAll();
    }

    public Optional<List<Purchase>> getByCliente(String clientId){
        return  purchaseRepository.getByClient(clientId);
    }

    public Purchase save(Purchase purchase){
        return  purchaseRepository.save(purchase);
    }
}
  • PurchaseController.java
package com.cesar1e.market.web.controller;

import com.cesar1e.market.domain.Product;
import com.cesar1e.market.domain.Purchase;
import com.cesar1e.market.domain.service.PurchaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/purchases")
public class PurchaseController {
    @Autowired
    private PurchaseService purchaseService;

    @GetMapping()
    public ResponseEntity<List<Purchase>> getAll(){
        return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
    }

    @GetMapping("/client/{clientId}")
    public ResponseEntity<List<Purchase>> getByClient(@PathVariable("clientId") String clientId){
        return purchaseService.getByCliente(clientId)
                .map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK))
                .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @PostMapping("/save")
    public ResponseEntity<Purchase> save(Purchase purchase){
        return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.CREATED);
    }

}

Hola, buen d铆a. Este es mi c贸digo
PurchaseService

@Service
public class PurchaseService {
    //Interfaz del repository.
    private PurchaseRepository purchaseRepository;

    public List<Purchase> getAll(){
        return purchaseRepository.getAll();
    }

    public Optional<List<Purchase>> getByClient(String clientId){
        return purchaseRepository.getByClient(clientId);
    }

    public Purchase save(Purchase purchase){
        return purchaseRepository.save(purchase);
    }

}```

**PurchaseController**


@RestController
@RequestMapping(value = 鈥/purchases鈥)

public class PurchaseController {
//Se inyecta el servicio
@Autowired
private PurchaseService purchaseService;

@GetMapping(value="/all")
public ResponseEntity<List<Purchase>> getAll(){
    return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK);
}

@GetMapping(value = "/client/{clientId}")
public ResponseEntity<List<Purchase>> getByClient(@PathVariable("clientId") String clientId){
    return purchaseService.getByClient(clientId).
            map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK)).
            orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

@PostMapping("/save")
public ResponseEntity<Purchase> save(@RequestBody Purchase purchase){
    //Retorna el http status 201 (CREATED)
    return new ResponseEntity<>(purchase, HttpStatus.CREATED);
}

}```

org.postgresql.util.PSQLException: ERROR: el operador no existe: character varying = integer

ideas?