leer antes:

desde un contenedor, entramos a la terminal interactiva y visualizamos las base de datos:

entramos al contenedor que vemos con docker ps (postgres_db) e interactuamos con la conssola interactiva (-it) y le indicamos el shell (bash, sh):

docker exec -it postgres_db bash

para ver todas las bases de datos por terminal (el usuario es admin):

 psql -U admin -d postgres -l


para ver la bases de datos visual en la web

esto es solo para debbiugear, checkear los registros (que se inserte)

hay primero que hacer un túnel SSH desde nuestra pc al servidor linux ubuntu server por ejemplo

ssh -L 8085:localhost:8085 axeldamian@192.168.0.xx

dejar esa terminal abierta para que el túnel SSH funcioné, esa terminal inicia sesión en el servidor

en ese ejemplo adminer escucha a su vez postgres, y el puerto 8085 de localhost del servidor está escuchando y redirijiendo a adminer, adminer está en un container de docker

luego localmente en localhost:8085 verás una interfaz web para acceder

en Servidor escribimos el nombre del contenedor docker donde está nuestro postgres, osea ‘postgres_db’


si ya creaste un contenedor docker para postgres, eliminalo y mapealo a 0.0.0.0:5432 así se puede acceder desde afuera

docker stop postgres_db
docker rm postgres_db

este comando crea automáticamente la base de datos mi_base_de_datos al iniciar el contenedor por primera vez:

docker run -d --name postgres_db -p 5432:5432 -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=abc -e POSTGRES_DB=mi_base_de_datos postgres:16

es muy importante mapear 5432 con 5432, sino desde afuera no voy a poder acceder a postgres, yo accedo desde afuera en la misma red local y por el puerto 5432, eso hace que de 0.0.0.0 (todas las interfaces) se acceda al puerto 5432

desde la interfaz web por adminer, podés ver todas las tablas de la base de datos:

algo que es muy importante es que crees una red (mi-red) y agregues el contenedor de docker (postgres_db) a esa red (mi-red):

docker network create mi-red

docker network connect mi-red postgres_db

para inspeccionar la red:

docker network inspect mi-red

listar todas las redes:

docker network ls

en el proyecto java en visual studio code debes tocar los archivos

build.gradle

debes agregar en el bloque dependencies el contenido:

    // Persistencia y driver Postgres
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'org.postgresql:postgresql'

y debes tenr agregadas las 2 dependencias: previamente

    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'

resources/application.properties

con el contenido agregado:

# Si ejecutás Spring Boot fuera de Docker (en local): usa localhost
# Si ejecutás Spring Boot en otro contenedor dentro de la misma red Docker: usa el nombre del servicio (ej. postgres-db)
spring.datasource.url=jdbc:postgresql://192.168.0.56:5432/mi_base_de_datos
spring.datasource.username=admin
spring.datasource.password=abc
spring.datasource.driver-class-name=org.postgresql.Driver

# Configuración JPA / Hibernate
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

debes crear una carpeta entity con las entidades (en este caso con la tabla de la base de datos users) y la entidad sse llama User

package com.leibnix.lgn.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "users") // Nombre de la tabla en Postgres
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String nombre;
    private String email;

    // Constructores
    public User() {}

    public User(String nombre, String email) {
        this.nombre = nombre;
        this.email = email;
    }

    // Getters y Setters
    public Long getId() { return id; }
    public String getNombre() { return nombre; }
    public void setNombre(String nombre) { this.nombre = nombre; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

una carpeta repository con el archivo UserRepository

package com.leibnix.lgn.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.leibnix.lgn.entity.User;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // No hace falta escribir nada aquí para operaciones básicas
}

luego desde el controller debes llamar al bean

package com.leibnix.lgn.controllers;

import org.springframework.http.ResponseEntity;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.leibnix.lgn.dtos.CredentialsCreate;
import com.leibnix.lgn.dtos.CredentialsLogin;
import com.leibnix.lgn.repository.UserRepository;

@RestController
@RequestMapping("/lgnx")
public class LgnxController {

    private final UserRepository userRepository;

    public LgnxController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }



    @PostMapping("/create")
    public ResponseEntity<String> create(@RequestBody CredentialsCreate json) {
        userRepository.save(new com.leibnix.lgn.entity.User(json.getUsername(), json.getPassword()));
        return ResponseEntity.ok("Login successful for user: " + json.getUsername());
    }



}

ejemplo:

osea instancias el bean con private final y luego lo inyectas desde su constructor:


    private final UserRepository userRepository;

    public LgnxController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

otra manera de hacerlo es con la annotation @Autowired


Una Entity representa la estructura de los datos (la tabla de la base de datos mapeada a un objeto Java) 

un Repository es la interfaz encargada de interactuar con esa base de datos (hacer las consultas SQL como buscar, guardar o borrar sin escribirlas a mano).

Entity (User.java): Es una clase Java annotated con @Entity que define los campos de la tabla en tu base de datos (por ejemplo, id, username, password). Cada instancia de esta clase representa una fila concreta en la tabla.

Repository (UserRepository.java): Es la capa de acceso a datos. Al extender de JpaRepository<User, Long>, Spring Data JPA te regala automáticamente métodos como .save(), .findById(), .findAll(), .delete(), etc.

el Repository genera automáticamente todas las operaciones SQL por ti basándose en la entidad

No necesitas escribir INSERT, UPDATE, SELECT o DELETE manualmente. Métodos como save(), findById(), findAll() o delete() vienen listos para usarse a través de la interfaz (como JpaRepository). Spring Data analiza la clase @Entity y traduce esas llamadas a las consultas que entiende la base de datos

sirven para muchísimas bases de datos. El patrón Entity-Repository es una abstracción. La forma en que interactúas con los objetos en el código Java sigue siendo casi idéntica sin importar el motor que haya detrás.

  • Bases de datos Relacionales (SQL): Usan Spring Data JPA. El mismo código te sirve para PostgreSQL, MySQL, MariaDB, Oracle, SQL Server o H2. Solo cambias el driver en las dependencias y la URL en application.properties

MongoDB también utiliza el patrón Entity-Repository, pero con pequeñas variaciones enfocadas en documentos NoSQL:

Repositorio (MongoRepository): En lugar de extender de JpaRepository, tu interfaz extiende de MongoRepository<Producto, String>.

Spring Data MongoDB: En lugar de JPA, agregas el starter spring-boot-starter-data-mongodb

Entidad (@Document): En lugar de la anotación @Entity, usas @Document. El @Id suele ser una cadena de texto (String u ObjectId) en vez de un número secuencial

en mongodb

Para usar MongoDB en Spring Boot con Spring Data MongoDB, el concepto de Repository es exactamente igual al de JPA (PostgreSQL), pero cambian las anotaciones de la entidad y la interfaz base del repositorio

para mongodb, en build.gradle:

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

en application.properties (mongodb)

spring.data.mongodb.uri=mongodb://192.168.0.56:27017/tu_base_de_datos
# Si requiere autenticación:
# spring.data.mongodb.uri=mongodb://usuario:password@192.168.0.56:27017/tu_base_de_datos?authSource=admin

entity en mongo es @Document(collection = “users”) // Nombre de la colección en Mongo y el repository extiende de otra clase:

@Repository
public interface UserRepository extends MongoRepository<User, String>

entity:

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "productos")
public class Producto {
    @Id
    private String id;
    private String nombre;

    // Getters y Setters
}

repository:

import org.springframework.data.mongodb.repository.MongoRepository;

public interface ProductoRepository extends MongoRepository<Producto, String> {
}

controller:

Producto p = new Producto();
p.setNombre("Monitor");

// Funciona igual que en Postgres, pero guarda un documento BSON/JSON en Mongo
productoRepository.save(p);

Esa es la principal ventaja de Spring Data: la API para interactuar con los datos (save, findById, delete) permanece uniforme, cambies a una base relacional como Postgres o a una basada en documentos como MongoDB


Derived Query Method

findByAgeGreaterThan

Es un método donde Spring Data JPA lee el nombre del método y genera la consulta SQL automáticamente en segundo plano

La consulta que genera internamente es equivalente a:

SELECT * FROM users WHERE age > ?;

Derivación de consultas por nombre (Query Methods): Si necesitas una consulta personalizada, muchas veces tampoco tienes que escribir SQL ni JPQL. Solo con nombrar el método siguiendo las convenciones de Spring, el framework genera la consulta automáticamente:

// Spring genera automáticamente el "SELECT * FROM users WHERE email = ?"
Optional<User> findByEmail(String email);

Custom JPQL/SQL Query

Es un método donde tú defines explícitamente la consulta usando la anotación @Query

Si quisieras combinar ambos criterios (buscar usuarios activos por rol Y mayores a cierta edad), no harías que un método llame al otro; simplemente crearías un tercer método que combine las condiciones:

List<User> findByActiveTrueAndRoleAndAgeGreaterThan(String role, int age);

con @Query:

@Query("SELECT u FROM User u WHERE u.active = true AND u.role = :role AND u.age > :age")
List<User> findActiveUsersByRoleAndAge(@Param("role") String role, @Param("age") int age);