Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Changelog

All notable changes to Jazzy Framework will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.1] - 2025-01-27

### Fixed
- **BREAKING**: Fixed deprecated Hibernate API usage in BaseRepositoryImpl
- Replaced deprecated `session.createQuery()` with `session.createMutationQuery()` for DELETE operations
- This ensures compatibility with future Hibernate versions and removes deprecation warnings

### Changed
- Updated Hibernate ORM from 6.4.1.Final to 6.4.10.Final for better performance and security
- Updated H2 database from 2.2.224 to 2.2.232 for latest bug fixes

### Added
- Enhanced transaction management in BaseRepositoryImpl with new helper methods:
- `executeInTransaction()` for operations that return values
- `executeInTransactionVoid()` for void operations
- Both methods include proper rollback handling for improved reliability

### Technical Details
- Improved error handling in repository operations
- Better transaction safety with automatic rollback on exceptions
- Removed FIXME comments related to deprecated API usage

## [0.3.0] - 2025-01-26

### Added
- Comprehensive Spring Data JPA-like query system
- Method name parsing for automatic query generation
- Support for @Query, @Modifying, and @QueryHint annotations
- Enhanced RepositoryFactory with query method support
- Database-level query execution for improved performance

### Fixed
- Resolved "socket hang up" errors in exception handling
- Fixed excessive logging in ORM components
- Improved code quality and reduced duplication in repository implementations

### Changed
- Migrated from memory-based filtering to database-level queries
- Enhanced query method parser with support for complex operations
- Improved error messages and debugging capabilities

## [0.2.0] - 2025-01-25

### Added
- Comprehensive dependency injection system
- Spring-like annotations (@Component, @Named, @Primary, @PostConstruct, @PreDestroy)
- Zero-configuration DI container
- Automatic component scanning and registration

### Changed
- Enhanced framework architecture with DI support
- Improved documentation and examples

## [0.1.0] - 2025-01-24

### Added
- Initial release of Jazzy Framework
- Basic web framework functionality
- Fluent API for request/response handling
- Simple routing system
- JSON operations support
- Basic validation system
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

Jazzy is a lightweight web framework for Java. It provides a minimal and easy-to-understand API for developing fast web applications with a structure inspired by Laravel and Spring Boot.

## 🚀 Latest Updates (v0.3.0)
## 🚀 Latest Updates (v0.3.1)

**NEW: Database Integration & ORM System!**
**NEW: Bug Fixes & API Improvements!**

Jazzy Framework 0.3 introduces comprehensive database integration with Spring Data JPA-like features:

Expand All @@ -21,6 +21,7 @@ Jazzy Framework 0.3 introduces comprehensive database integration with Spring Da

| Version | Release Date | Key Features |
|---------|-------------|--------------|
| **0.3.1** | 2025 | 🔧 **Bug Fixes & Improvements** - Fixed deprecated Hibernate APIs, enhanced transaction management, dependency updates |
| **0.3.0** | 2025 | 🆕 **Database Integration** - Hibernate/JPA, Spring Data JPA-like repositories, automatic query generation, transaction management |
| **0.2.0** | 2025 | 🆕 **Dependency Injection System**, Spring-like annotations, automatic component discovery, lifecycle management |
| **0.1.0** | 2025 | Core framework with routing, request/response handling, JSON utilities, validation system, metrics |
Expand Down Expand Up @@ -58,6 +59,7 @@ Jazzy Framework 0.3 introduces comprehensive database integration with Spring Da
- **Transaction Management**: Automatic transaction handling with proper rollback
- **Entity Discovery**: Automatic entity scanning and configuration
- **Connection Pooling**: HikariCP for production-ready database connections
- **Multiple Database Support**: H2, PostgreSQL, MySQL, Oracle support

## Quick Start

Expand Down
77 changes: 58 additions & 19 deletions src/main/java/jazzyframework/data/BaseRepositoryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.logging.Logger;

/**
Expand Down Expand Up @@ -108,11 +110,8 @@ public T save(T entity) {
throw new IllegalArgumentException("Entity must not be null");
}

try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
T savedEntity = session.merge(entity);
transaction.commit();
return savedEntity;
try {
return executeInTransaction(session -> session.merge(entity));
} catch (Exception e) {
logger.severe("Error saving entity: " + e.getMessage());
throw new RuntimeException("Failed to save entity", e);
Expand Down Expand Up @@ -152,11 +151,8 @@ public Optional<T> findById(ID id) {
throw new IllegalArgumentException("ID must not be null");
}

try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
T entity = session.get(entityClass, id);
transaction.commit();
return Optional.ofNullable(entity);
try {
return executeInTransaction(session -> Optional.ofNullable(session.get(entityClass, id)));
} catch (Exception e) {
logger.severe("Error finding entity by ID: " + e.getMessage());
throw new RuntimeException("Failed to find entity", e);
Expand Down Expand Up @@ -244,13 +240,13 @@ public void deleteById(ID id) {
throw new IllegalArgumentException("ID must not be null");
}

try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
T entity = session.get(entityClass, id);
if (entity != null) {
session.remove(entity);
}
transaction.commit();
try {
executeInTransactionVoid(session -> {
T entity = session.get(entityClass, id);
if (entity != null) {
session.remove(entity);
}
});
logger.fine("Deleted entity with ID: " + id);
} catch (Exception e) {
logger.severe("Error deleting entity by ID: " + e.getMessage());
Expand Down Expand Up @@ -290,7 +286,7 @@ public void deleteAllById(Iterable<ID> ids) {

try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
Query<?> query = session.createQuery( // FIXME: deprecated method
var query = session.createMutationQuery(
"DELETE FROM " + entityName + " e WHERE e." + idFieldName + " IN (:ids)");
query.setParameterList("ids", idList);
int deletedCount = query.executeUpdate();
Expand Down Expand Up @@ -329,7 +325,7 @@ public void deleteAll(Iterable<T> entities) {
public void deleteAll() {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
Query<?> query = session.createQuery("DELETE FROM " + entityName); // FIXME: deprecated method
var query = session.createMutationQuery("DELETE FROM " + entityName);
int deletedCount = query.executeUpdate();
transaction.commit();
logger.fine("Deleted all " + deletedCount + " entities of type: " + entityName);
Expand Down Expand Up @@ -386,4 +382,47 @@ public void deleteInBatch(Iterable<T> entities) {
public void deleteAllInBatch() {
deleteAll();
}

/**
* Helper method to execute operations in a transaction with proper rollback handling.
*
* @param operation the operation to execute
* @param <R> the return type
* @return the result of the operation
*/
protected <R> R executeInTransaction(Function<Session, R> operation) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
try {
R result = operation.apply(session);
transaction.commit();
return result;
} catch (Exception e) {
if (transaction.isActive()) {
transaction.rollback();
}
throw e;
}
}
}

/**
* Helper method to execute void operations in a transaction with proper rollback handling.
*
* @param operation the operation to execute
*/
protected void executeInTransactionVoid(Consumer<Session> operation) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
try {
operation.accept(session);
transaction.commit();
} catch (Exception e) {
if (transaction.isActive()) {
transaction.rollback();
}
throw e;
}
}
}
}