This document outlines the improvements made to the database code to make it cleaner, more readable, and more maintainable.
- Thread-safe Singleton Pattern: Implemented proper double-checked locking for thread safety
- Configuration Management: Added support for external configuration via
database.properties - Better Error Handling: Improved exception handling with meaningful error messages
- Connection Validation: Added automatic connection validation and reconnection
- Resource Management: Proper resource cleanup and connection testing
- Multiple Test URLs: Tests connectivity against multiple URLs for better reliability
- Configurable Timeouts: Support for custom connection and read timeouts
- Async Support: Added asynchronous connectivity checking
- Detailed Reporting: Provides detailed connectivity information
- Better Error Handling: Improved error logging and handling
- Common Operations: Centralized common database operations
- Generic Query Execution: Type-safe query execution with result mapping
- Batch Operations: Support for batch updates and transactions
- Error Logging: Consistent error logging across all DAOs
- Resource Management: Automatic resource cleanup
- Extends BaseDAO: Inherits common functionality from BaseDAO
- SQL Constants: All SQL queries defined as constants
- Better Method Organization: Clear separation of concerns
- Enhanced Features: Added search, filtering, and pagination support
- Improved Error Handling: Consistent error handling and logging
- Common Constants: Centralized table and column names
- Utility Methods: Helper methods for common database operations
- SQL Building: Methods to build complex SQL queries
- Resource Management: Safe resource cleanup utilities
- Security: SQL logging with sensitive data removal
src/main/java/DB/
├── DBConnection.java # Enhanced connection management
├── InternetConnectionChecker.java # Improved connectivity checking
└── DatabaseUtils.java # New utility class
src/main/java/services/
├── BaseDAO.java # New base class for all DAOs
├── ProductDAO.java # Refactored to extend BaseDAO
└── [Other DAO classes] # Should be refactored similarly
src/main/resources/
└── database.properties # Database configuration file
// Get database connection
Connection conn = DBConnection.getInstance().getConnection();
// Test connection
boolean isConnected = DBConnection.getInstance().testConnection();InternetConnectionChecker checker = new InternetConnectionChecker();
// Basic check
boolean isOnline = checker.isInternetAvailable();
// Async check
CompletableFuture<Boolean> future = checker.isInternetAvailableAsync();
// Detailed information
ConnectivityInfo info = checker.getConnectivityInfo();public class MyDAO extends BaseDAO {
public List<MyEntity> getAllEntities() {
return executeQuery("SELECT * FROM my_table", null, this::mapResultSet);
}
public boolean addEntity(MyEntity entity) {
Object[] params = {entity.getName(), entity.getValue()};
return executeUpdate("INSERT INTO my_table (name, value) VALUES (?, ?)", params) > 0;
}
private MyEntity mapResultSet(ResultSet rs) {
// Map ResultSet to entity
}
}// Build WHERE clause
List<String> conditions = Arrays.asList("status = 'active'", "type = 'user'");
String whereClause = DatabaseUtils.buildWhereClause(conditions, "AND");
// Safe resource cleanup
DatabaseUtils.closeResources(rs, stmt, conn);
// Check table existence
boolean exists = DatabaseUtils.tableExists(connection, "my_table");Create src/main/resources/database.properties:
db.url=jdbc:mysql://localhost:3306/pos_db?useSSL=false&serverTimezone=UTC
db.user=root
db.password=
db.pool.initialSize=5
db.pool.maxSize=20- Extend BaseDAO for all new DAO classes
- Use the provided utility methods instead of writing custom database code
- Leverage the built-in error handling and logging
- Define SQL queries as constants at the top of DAO classes
- Use DatabaseUtils constants for table and column names
- Avoid hardcoding SQL strings in methods
- Use the provided logError method for consistent error logging
- Handle exceptions appropriately in your business logic
- Don't ignore SQL exceptions
- Use try-with-resources for database operations
- Use DatabaseUtils.closeResources for manual cleanup
- Always close connections, statements, and result sets
- Use executeTransaction for multi-step operations
- Always handle rollback in case of errors
- Keep transactions as short as possible
- Extend BaseDAO: Change class declaration to extend BaseDAO
- Move SQL to Constants: Define all SQL queries as private static final constants
- Use Utility Methods: Replace custom database code with BaseDAO methods
- Update Error Handling: Use logError method instead of printStackTrace
- Add Documentation: Add JavaDoc comments for all public methods
// Before
public class OldDAO {
public List<Product> getAllProducts() {
List<Product> products = new ArrayList<>();
try (Connection conn = DBConnection.getInstance().getConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM product");
ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
products.add(mapResultSet(rs));
}
} catch (SQLException e) {
e.printStackTrace();
}
return products;
}
}
// After
public class NewDAO extends BaseDAO {
private static final String SELECT_ALL_PRODUCTS = "SELECT * FROM product";
public List<Product> getAllProducts() {
return executeQuery(SELECT_ALL_PRODUCTS, null, this::mapResultSet);
}
}- Maintainability: Centralized code reduces duplication
- Readability: Clear structure and consistent patterns
- Reliability: Better error handling and resource management
- Performance: Optimized connection management and batch operations
- Security: Proper SQL logging and parameter handling
- Testability: Easier to unit test with dependency injection support
- Connection Pooling: Implement proper connection pooling
- Caching: Add result caching for frequently accessed data
- Monitoring: Add database performance monitoring
- Migration Tools: Database schema migration utilities
- Query Builder: Advanced SQL query builder
- Audit Logging: Database operation audit trails