Implementação do padrão de projeto DAO (Data Access Object) com Generics em Java puro, sem frameworks externos. O objetivo é demonstrar como abstrair operações de persistência de forma reutilizável, tipada e extensível.
src/
├── domain/
│ ├── GenericDomain.java # Classe base abstrata com id genérico
│ ├── UserDomain.java # Entidade de usuário (id: Integer, gerado automaticamente)
│ ├── ClientDomain.java # Entidade de cliente (id: String)
│ └── MenuOption.java # Enum com as opções do menu interativo
├── dao/
│ ├── GenericDAO.java # DAO genérico com operações CRUD
│ ├── UserDAO.java # DAO específico de usuário (auto-incremento de id)
│ └── ClientDAO.java # DAO específico de cliente
├── Exceptions/
│ ├── EntityNotFoundException.java # Lançada quando um id não é encontrado
│ ├── EmptyStorageException.java # Lançada quando o armazenamento está vazio
│ └── ValidatorException.java # Lançada quando a validação de entidade falha
├── UserValidator/
│ ├── Validator.java # Interface genérica de validação
│ └── UserDomainValidator.java # Validador de regras de negócio para UserDomain
└── test/
└── DAOTest.java # Menu interativo via terminal + testes com assert
save(T)— salva uma entidadesaveAll(T...)— salva múltiplas entidadesfindById(ID)— busca por id com retornoOptional<T>findByIdOrThrow(ID)— busca por id, lançandoEntityNotFoundExceptionse não encontradofind(Predicate<T>)— busca por qualquer critério via lambdaexists(ID)— verifica se um id existeupdate(ID, T)— atualiza uma entidade, lançandoEntityNotFoundExceptionse o id não existirdelete(T)— remove por objetodeleteById(ID)— remove por idfindAll()— retorna lista imutável de todas as entidades (retorna lista vazia se o storage estiver vazio)count()— retorna o total de entidades salvasverifyStorage()— lançaEmptyStorageExceptionse o armazenamento estiver vazio
- Armazenamento interno via
LinkedHashMap<ID, T>para busca em O(1) e preservação de ordem de inserção findAll()retornaCollections.unmodifiableListpara proteger o estado interno; retorna lista vazia em vez de lançar exceção- Exceções customizadas:
EntityNotFoundException,EmptyStorageExceptioneValidatorException @SafeVarargsemsaveAllpara suprimir warning de heap pollution em genericsUserDAOimplementa auto-incremento de id via camponextId- Camada de validação desacoplada via interface genérica
Validator<T>e implementaçãoUserDomainValidator - Menu interativo via terminal com
Scannere enumMenuOptionpara navegação por operações CRUD
- Java 21
- Sem dependências externas
Implementation of the DAO (Data Access Object) design pattern using Generics in plain Java, with no external frameworks. The goal is to demonstrate how to abstract persistence operations in a reusable, type-safe, and extensible way.
src/
├── domain/
│ ├── GenericDomain.java # Abstract base class with generic id
│ ├── UserDomain.java # User entity (id: Integer, auto-generated)
│ ├── ClientDomain.java # Client entity (id: String)
│ └── MenuOption.java # Enum with interactive menu options
├── dao/
│ ├── GenericDAO.java # Generic DAO with full CRUD operations
│ ├── UserDAO.java # User-specific DAO (auto-increment id)
│ └── ClientDAO.java # Client-specific DAO
├── Exceptions/
│ ├── EntityNotFoundException.java # Thrown when an id is not found
│ ├── EmptyStorageException.java # Thrown when storage is empty
│ └── ValidatorException.java # Thrown when entity validation fails
├── UserValidator/
│ ├── Validator.java # Generic validation interface
│ └── UserDomainValidator.java # Business rule validator for UserDomain
└── test/
└── DAOTest.java # Interactive terminal menu + assert-based tests
save(T)— persists an entitysaveAll(T...)— persists multiple entities at oncefindById(ID)— finds by id, returnsOptional<T>findByIdOrThrow(ID)— finds by id, throwsEntityNotFoundExceptionif not foundfind(Predicate<T>)— finds by any criteria using a lambdaexists(ID)— checks whether an id existsupdate(ID, T)— updates an entity, throwingEntityNotFoundExceptionif id is not founddelete(T)— removes by objectdeleteById(ID)— removes by idfindAll()— returns an unmodifiable list of all entities (returns empty list if storage is empty)count()— returns the total number of stored entitiesverifyStorage()— throwsEmptyStorageExceptionif storage is empty
- Internal storage uses
LinkedHashMap<ID, T>for O(1) lookups and insertion-order preservation findAll()returnsCollections.unmodifiableListto protect internal state; returns empty list instead of throwing- Custom exceptions:
EntityNotFoundException,EmptyStorageException, andValidatorException @SafeVarargsonsaveAllto suppress heap pollution warning on generic varargsUserDAOimplements auto-increment id vianextIdfield- Decoupled validation layer via generic
Validator<T>interface andUserDomainValidatorimplementation - Interactive terminal menu using
ScannerandMenuOptionenum for CRUD navigation
- Java 21
- No external dependencies