Estado: en construcción. Fases 1 y 2 completas; UI Swing y demo de concurrencia pendientes (Fases 3-5). README definitivo en Fase 5.
Aplicación Java de escritorio que simula la gestión de clientes, cuentas y transferencias bancarias. Proyecto de portafolio basado en las tres asignaturas de Java de Duoc UC: Fundamentos, POO I y POO II.
- Jerarquía polimórfica:
Cuentaabstracta +CuentaCorriente/CuentaAhorro, concalcularInteres()distinto por subclase. - Patrón DAO: interfaces (
ClienteDAO,CuentaDAO,TransaccionDAO) e implementaciones JDBC puras. PreparedStatementen todas las queries (anti SQL injection).BigDecimalconRoundingMode.HALF_EVEN(banker's rounding) para dinero.- 6 excepciones de dominio nominales (
SaldoInsuficienteException,CuentaInactivaException,MontoInvalidoException,CuentaNoExisteException,ClienteNoExisteException,ClienteTieneCuentasException). DemoDAOcomo smoke test que imprime el estado completo de la BD.
TransferenciaServiceconReentrantLockpor cuenta enConcurrentHashMap<Long, ReentrantLock>.- Lock-ordering por id ascendente para prevenir deadlock A↔B.
- Transacciones JDBC (
setAutoCommit(false)/commit/rollback) sobre una únicaConnectionpara débito + crédito + INSERT entransaccion, vía sobrecarga transaccional en los DAOs. ClienteServicetraduceSQLState 23503(FK violation) enClienteTieneCuentasExceptioncon mensaje accionable.CuentaServicevalidaclienteIdantes de insertar y lanzaClienteNoExisteExceptionsi no existe.- 9 tests JUnit 5 verdes, BD aislada
banco_test:- 50 transferencias concurrentes preservan el saldo total (
AtomicInteger). - 60 transferencias en direcciones opuestas no se bloquean (
@Timeout(5s)). - Rollback verificado bajo saldo insuficiente (sin tocar la BD).
- Auto-transferencia rechazada antes de adquirir locks.
- Caminos felices y errores de validación de los servicios CRUD.
- 50 transferencias concurrentes preservan el saldo total (
VentanaPrincipalconJTabbedPane(Clientes / Cuentas / Transferencias).- CRUDs visuales para
ClienteyCuenta. JDialogmodal para transferencia con validación previa.- Botón "Aplicar interés mensual" para demostrar polimorfismo en vivo.
- Panel con N hilos / M transferencias configurables.
- Log en tiempo real de éxitos y rechazos.
- Verificación visual de saldo total preservado.
- README definitivo con capturas de la UI.
- Documentación expandida (Javadoc en clases públicas).
- Verificación end-to-end desde clon limpio.
- Java 21 LTS (text blocks, switch expressions, pattern matching)
- Maven (compiler, surefire, exec plugins)
- PostgreSQL 16 en Docker
- JDBC puro — sin ORM, sin Spring; toda la persistencia se ve y se entiende
- Java Swing (a partir de Fase 3)
- JUnit 5 Jupiter
cl.rvasquez.banco
├── modelo/ Cliente, Cuenta (abstract), CuentaCorriente, CuentaAhorro,
│ Transaccion, TipoCuenta, EstadoTransaccion
├── dao/ Interfaces ClienteDAO, CuentaDAO, TransaccionDAO
│ └── impl/ Implementaciones JDBC (xxxDAOImpl)
├── servicio/ ClienteService, CuentaService, TransferenciaService
├── excepcion/ 6 excepciones de dominio nominales (extends RuntimeException)
├── util/ ConexionBD (lectura de properties + override por env vars)
├── Main Punto de entrada (Fase 0: SELECT 1)
└── DemoDAO Smoke test de la capa de datos (Fase 1)
PreparedStatementsiempre. No hay concatenación de SQL en ningún DAO, ni siquiera en queries triviales — política única para que sea trivial de auditar.- Cláusula
RETURNINGde PostgreSQL. Insertar y rescatarid/fechaen un solo round-trip, singetGeneratedKeys(). BigDecimalcon escala 4 yHALF_EVEN. Schema usaNUMERIC(19,4); el redondeo bancario evita el sesgo delHALF_UPclásico.- Excepciones de dominio nominales. Cada regla de negocio rota tiene su
propia clase en
excepcion/. La vista las captura por tipo, sin parsear mensajes ni inspeccionarSQLException. - Lock-ordering por id ascendente. Antes de operar sobre dos cuentas, el servicio toma siempre primero el lock del id menor. Esto convierte el deadlock clásico A→B vs B→A en simple contención.
- Sobrecarga transaccional en los DAOs. Cada DAO expone un método
autónomo (abre y cierra su
Connection) y una variante que recibe unaConnectionexterna y NO la cierra. La segunda permite que el servicio componga varias operaciones bajo una misma transacción. - Encapsulación reforzada en
Cuenta. El camposaldono tiene setter público: solo se modifica víaaplicarDebito/aplicarCredito, que validan saldo, monto y estado activo antes de mutar. - Aislamiento de tests. El
surefirepasaPOSTGRES_DB=banco_testcomo env var, ysql/02-test-db.sqldefine ese schema sin datos semilla. Cada test trunca y siembra sus propios datos.
Para desarrollo local no necesitas configurar nada: docker compose up -d
funciona con valores por defecto definidos tanto en docker-compose.yml
como en src/main/resources/application.properties.
Si quieres personalizar las credenciales (por ejemplo, para no usar
banco/banco/banco en una demo pública), copia la plantilla y edítala:
cp .env.example .env
# edita .env con tus valoresTanto Compose como la aplicación Java leen las mismas variables:
| Variable | Default | Uso |
|---|---|---|
POSTGRES_DB |
banco |
Nombre de la base de datos |
POSTGRES_USER |
banco |
Usuario de Postgres |
POSTGRES_PASSWORD |
banco |
Contraseña |
El archivo .env está en .gitignore y nunca se commitea; .env.example
sirve solo como plantilla.
Postgres queda expuesto en el host en el puerto 15432 (saltamos fuera del rango 543x para evitar choques con otros Postgres locales). Para inspeccionar la base con un cliente externo:
psql -h localhost -p 15432 -U banco -d bancodocker compose up -d
# Smoke test de la capa de datos: lista clientes + cuentas + transacciones,
# imprime intereses calculados polimórficamente (0 para CORRIENTE,
# saldo*0.005 para AHORRO).
mvn -q compile exec:java -Dexec.mainClass=cl.rvasquez.banco.DemoDAO
# Suite de tests contra banco_test (la BD `banco` no se toca).
# Debe imprimir: Tests run: 9, Failures: 0, Errors: 0 — BUILD SUCCESS
mvn testProyecto basado en las tres asignaturas de Java cursadas en Duoc UC (Analista Programador Computacional):
- Fundamentos de Programación en Java
- Desarrollo Orientado a Objetos I
- Desarrollo Orientado a Objetos II