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’m going to to share how is going my project until now: https://github.com/borisbikes/platzi/tree/main/Spring/platzi-market
It’s 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?