Implement JPA auditing and soft delete supportFinal shopmate pr#132
Implement JPA auditing and soft delete supportFinal shopmate pr#132SRokesh-28 wants to merge 12 commits into
Conversation
Added Spring Data JPA auditing support annotations to BaseAuditableEntity. Changes: * Added @CreatedDate for automatic creation timestamp tracking * Added @LastModifiedDate for automatic update timestamp tracking * Added @EntityListeners(AuditingEntityListener.class) to enable auditing event handling * Added required Spring Data JPA auditing imports
Enabled Spring Data JPA auditing support in the application. Changes: * Added @EnableJpaAuditing to the main Spring Boot application class * Activated automatic auditing support for @CreatedDate and @LastModifiedDate annotations * Enabled automatic population of audit fields for entities extending BaseAuditableEntity
Added Spring Data JPA auditing support to DomainEntity. Changes: * Added @EntityListeners(AuditingEntityListener.class) * Added @CreatedDate annotation for automatic creation timestamp tracking * Added @LastModifiedDate annotation for automatic update timestamp tracking * Enabled auditing support for entities extending DomainEntity
Added Hibernate soft delete support to the Category entity. Changes: * Added @SQLDelete annotation to update the deleted flag instead of physically removing records * Added @where annotation to automatically filter out deleted records from queries * Enabled logical delete behavior for the categories table
Added Hibernate soft delete support to the Item entity. Changes: * Added @SQLDelete annotation to update the deleted flag instead of physically removing records * Added @where annotation to automatically filter out deleted records from queries * Enabled logical delete behavior for the items table
Added Hibernate soft delete support to the ListItem entity. Changes: * Added @SQLDelete annotation to update the deleted flag instead of physically removing records * Added @where annotation to automatically filter out deleted records from queries * Enabled logical delete behavior for the list_items table
Added Hibernate soft delete support to the Unit entity. Changes: * Added @SQLDelete annotation to update the deleted flag instead of physically removing records * Added @where annotation to automatically filter out deleted records from queries * Enabled logical delete behavior for the units table
Added Hibernate soft delete support to the User entity. Changes: * Added @SQLDelete annotation to update the deleted flag instead of physically removing records * Added @where annotation to automatically filter out deleted records from queries * Enabled logical delete behavior for the users table
Added Hibernate soft delete support to the ListPermission entity. Changes: * Added @SQLDelete annotation to update the deleted flag instead of physically removing records * Added @where annotation to automatically filter out deleted records from queries * Enabled logical delete behavior for the list_user_permissions table
Added Hibernate soft delete support to the ShoppingList entity. Changes: * Added @SQLDelete annotation to update the deleted flag instead of physically removing records * Added @where annotation to automatically filter out deleted records from queries * Enabled logical delete behavior for the lists table
📝 WalkthroughWalkthroughThis PR introduces two foundational infrastructure features: Spring Data JPA auditing to automatically track entity creation and modification timestamps, and Hibernate soft-delete semantics to mark records as deleted instead of physically removing them from the database. ChangesData Persistence Infrastructure
🎯 2 (Simple) | ⏱️ ~12 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (7)
backend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ListPermission.java (1)
16-17: ⚡ Quick winAdjust import ordering for added Hibernate annotations.
Keep third-party imports grouped before project package imports.
As per coding guidelines, "Order imports as: java., jakarta., org.springframework., third-party, project packages in com.omatheusmesmo.shoppmate. domain".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ListPermission.java` around lines 16 - 17, The new Hibernate annotation imports in ListPermission (org.hibernate.annotations.SQLDelete and org.hibernate.annotations.Where) are out of the prescribed import order; reorder the imports so java.*, jakarta.*, org.springframework.* come first, then third-party imports (org.hibernate.*) and finally project package imports under com.omatheusmesmo.shoppmate.* in the ListPermission.java import block to comply with the project's import ordering guideline.backend/src/main/java/com/omatheusmesmo/shoppmate/item/entity/Item.java (1)
15-16: ⚡ Quick winReorder newly added Hibernate imports.
Place third-party imports before project imports per repository ordering rules.
As per coding guidelines, "Order imports as: java., jakarta., org.springframework., third-party, project packages in com.omatheusmesmo.shoppmate. domain".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/src/main/java/com/omatheusmesmo/shoppmate/item/entity/Item.java` around lines 15 - 16, The two Hibernate imports (org.hibernate.annotations.SQLDelete and org.hibernate.annotations.Where) are third-party and must be placed before the project package imports; update the import ordering in Item.java so that java.*/jakarta.*/org.springframework.* remain first, then the org.hibernate.* imports, and only after them the com.omatheusmesmo.* project imports—locate the imports around the Item class declaration and move the SQLDelete and Where lines accordingly.backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/DomainEntity.java (1)
11-15: ⚡ Quick winAlign import block with project order.
The new imports should be grouped in the required package order.
As per coding guidelines, "Order imports as: java., jakarta., org.springframework., third-party, project packages in com.omatheusmesmo.shoppmate. domain".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/DomainEntity.java` around lines 11 - 15, Reorder the import block in DomainEntity.java to follow project guidelines: place java.* imports first (if any), then jakarta.* (e.g., jakarta.persistence.EntityListeners), then org.springframework.* (e.g., org.springframework.data.annotation.CreatedDate, org.springframework.data.annotation.LastModifiedDate, org.springframework.data.jpa.domain.support.AuditingEntityListener), followed by any third-party and then project packages; update the import section around the DomainEntity class so the imports are grouped and ordered exactly as specified.backend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ShoppingList.java (2)
19-20: ⚡ Quick winPlace new Hibernate imports in the configured order.
Reorder this block to keep third-party imports before
com.omatheusmesmo.shoppmate.*imports.As per coding guidelines, "Order imports as: java., jakarta., org.springframework., third-party, project packages in com.omatheusmesmo.shoppmate. domain".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ShoppingList.java` around lines 19 - 20, The import order in ShoppingList.java is incorrect: move the Hibernate imports (org.hibernate.annotations.SQLDelete and org.hibernate.annotations.Where) so that third-party imports come before the project's own packages (com.omatheusmesmo.shoppmate.*); update the import block to follow the rule "java.*, jakarta.*, org.springframework.*, third-party, com.omatheusmesmo.shoppmate.*" so the org.hibernate.* entries appear above any com.omatheusmesmo.shoppmate.* imports in the file.
23-24: Consider indexing for soft-delete query paths.Since
deleted = falsebecomes a global filter, ensure DB indexes support common access paths (often composite indexes, not justdeletedalone) to avoid regressions at scale.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ShoppingList.java` around lines 23 - 24, The soft-delete filter on the ShoppingList entity (annotations `@SQLDelete` and `@Where`, table "lists", boolean field "deleted") will make queries include "deleted = false" globally — add appropriate DB indexes via a migration to cover these common access paths (e.g., composite indexes that include deleted plus the frequent query columns such as ownerId/userId, created_at, or whatever columns your queries filter/sort by) rather than a standalone deleted index; update DB migration scripts to create composite indexes like (owner_id, deleted) or (user_id, deleted, created_at) matching the actual repository queries, and ensure the index names and migration apply to the "lists" table so the global filter remains performant.backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/BaseAuditableEntity.java (1)
12-15: ⚡ Quick winReorder imports to match repository convention.
Move imports to
java.*,jakarta.*,org.springframework.*, third-party, thencom.omatheusmesmo.shoppmate.*.As per coding guidelines, "Order imports as: java., jakarta., org.springframework., third-party, project packages in com.omatheusmesmo.shoppmate. domain".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/BaseAuditableEntity.java` around lines 12 - 15, Reorder the import block in BaseAuditableEntity so it follows the repository convention: java.* first (if any), then jakarta.* (e.g., jakarta.persistence.EntityListeners), then org.springframework.* (e.g., org.springframework.data.annotation.CreatedDate, org.springframework.data.annotation.LastModifiedDate, org.springframework.data.jpa.domain.support.AuditingEntityListener), then any third‑party, then project packages under com.omatheusmesmo.shoppmate.*; adjust the existing imports accordingly to match that sequence.backend/src/main/java/com/omatheusmesmo/shoppmate/unit/entity/Unit.java (1)
13-14: ⚡ Quick winReplace deprecated
@Wherewith@SQLRestrictionfor forward compatibility with Hibernate 6.3+.
@Whereis deprecated in Hibernate 6.3 and later;@SQLRestrictionis the recommended replacement. Update the import and annotation:Suggested update
-import org.hibernate.annotations.Where; +import org.hibernate.annotations.SQLRestriction; @@ -@Where(clause = "deleted = false") +@SQLRestriction("deleted = false")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/src/main/java/com/omatheusmesmo/shoppmate/unit/entity/Unit.java` around lines 13 - 14, Replace the deprecated `@Where` annotation on the Unit entity with `@SQLRestriction` for Hibernate 6.3+ compatibility: remove the import of org.hibernate.annotations.Where, add the import org.hibernate.annotations.SQLRestriction, and replace the `@Where`(clause = "deleted = false") annotation on the Unit class with `@SQLRestriction`(value = "deleted = false") while keeping the existing `@SQLDelete`(sql = "UPDATE units SET deleted = true WHERE id=?") annotation intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/BaseAuditableEntity.java`:
- Around line 29-35: The audit fields in BaseAuditableEntity (createdAt,
updatedAt) must not be mutable from application code: remove or make any public
setters for createdAt and updatedAt non-public (private or protected) so callers
cannot override them, and mark createdAt as non-updatable at the JPA level by
adding updatable = false to its `@Column` (e.g., `@Column`(name = "created_at",
updatable = false)). Keep the `@CreatedDate` and `@LastModifiedDate` annotations so
the auditing framework can still set the values.
In
`@backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/DomainEntity.java`:
- Around line 32-38: The audit fields in DomainEntity (createdAt with
`@CreatedDate` and updatedAt with `@LastModifiedDate`) are currently writable
because the class-level `@Setter` exposes them; remove their public setters by
disabling Lombok setters for these fields (e.g., `@Setter`(AccessLevel.NONE) on
createdAt and updatedAt) or otherwise make their setters non-public, and mark
createdAt as non-updatable in the JPA mapping (add updatable = false on the
`@Column` for createdAt) so callers cannot overwrite audited timestamps.
---
Nitpick comments:
In `@backend/src/main/java/com/omatheusmesmo/shoppmate/item/entity/Item.java`:
- Around line 15-16: The two Hibernate imports
(org.hibernate.annotations.SQLDelete and org.hibernate.annotations.Where) are
third-party and must be placed before the project package imports; update the
import ordering in Item.java so that java.*/jakarta.*/org.springframework.*
remain first, then the org.hibernate.* imports, and only after them the
com.omatheusmesmo.* project imports—locate the imports around the Item class
declaration and move the SQLDelete and Where lines accordingly.
In
`@backend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ListPermission.java`:
- Around line 16-17: The new Hibernate annotation imports in ListPermission
(org.hibernate.annotations.SQLDelete and org.hibernate.annotations.Where) are
out of the prescribed import order; reorder the imports so java.*, jakarta.*,
org.springframework.* come first, then third-party imports (org.hibernate.*) and
finally project package imports under com.omatheusmesmo.shoppmate.* in the
ListPermission.java import block to comply with the project's import ordering
guideline.
In
`@backend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ShoppingList.java`:
- Around line 19-20: The import order in ShoppingList.java is incorrect: move
the Hibernate imports (org.hibernate.annotations.SQLDelete and
org.hibernate.annotations.Where) so that third-party imports come before the
project's own packages (com.omatheusmesmo.shoppmate.*); update the import block
to follow the rule "java.*, jakarta.*, org.springframework.*, third-party,
com.omatheusmesmo.shoppmate.*" so the org.hibernate.* entries appear above any
com.omatheusmesmo.shoppmate.* imports in the file.
- Around line 23-24: The soft-delete filter on the ShoppingList entity
(annotations `@SQLDelete` and `@Where`, table "lists", boolean field "deleted") will
make queries include "deleted = false" globally — add appropriate DB indexes via
a migration to cover these common access paths (e.g., composite indexes that
include deleted plus the frequent query columns such as ownerId/userId,
created_at, or whatever columns your queries filter/sort by) rather than a
standalone deleted index; update DB migration scripts to create composite
indexes like (owner_id, deleted) or (user_id, deleted, created_at) matching the
actual repository queries, and ensure the index names and migration apply to the
"lists" table so the global filter remains performant.
In
`@backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/BaseAuditableEntity.java`:
- Around line 12-15: Reorder the import block in BaseAuditableEntity so it
follows the repository convention: java.* first (if any), then jakarta.* (e.g.,
jakarta.persistence.EntityListeners), then org.springframework.* (e.g.,
org.springframework.data.annotation.CreatedDate,
org.springframework.data.annotation.LastModifiedDate,
org.springframework.data.jpa.domain.support.AuditingEntityListener), then any
third‑party, then project packages under com.omatheusmesmo.shoppmate.*; adjust
the existing imports accordingly to match that sequence.
In
`@backend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/DomainEntity.java`:
- Around line 11-15: Reorder the import block in DomainEntity.java to follow
project guidelines: place java.* imports first (if any), then jakarta.* (e.g.,
jakarta.persistence.EntityListeners), then org.springframework.* (e.g.,
org.springframework.data.annotation.CreatedDate,
org.springframework.data.annotation.LastModifiedDate,
org.springframework.data.jpa.domain.support.AuditingEntityListener), followed by
any third-party and then project packages; update the import section around the
DomainEntity class so the imports are grouped and ordered exactly as specified.
In `@backend/src/main/java/com/omatheusmesmo/shoppmate/unit/entity/Unit.java`:
- Around line 13-14: Replace the deprecated `@Where` annotation on the Unit entity
with `@SQLRestriction` for Hibernate 6.3+ compatibility: remove the import of
org.hibernate.annotations.Where, add the import
org.hibernate.annotations.SQLRestriction, and replace the `@Where`(clause =
"deleted = false") annotation on the Unit class with `@SQLRestriction`(value =
"deleted = false") while keeping the existing `@SQLDelete`(sql = "UPDATE units SET
deleted = true WHERE id=?") annotation intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0ab4bb4e-bfda-4858-a76e-14024dcd058b
📒 Files selected for processing (10)
backend/src/main/java/com/omatheusmesmo/shoppmate/ShoppMateApplication.javabackend/src/main/java/com/omatheusmesmo/shoppmate/category/entity/Category.javabackend/src/main/java/com/omatheusmesmo/shoppmate/item/entity/Item.javabackend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ListItem.javabackend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ListPermission.javabackend/src/main/java/com/omatheusmesmo/shoppmate/list/entity/ShoppingList.javabackend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/BaseAuditableEntity.javabackend/src/main/java/com/omatheusmesmo/shoppmate/shared/domain/DomainEntity.javabackend/src/main/java/com/omatheusmesmo/shoppmate/unit/entity/Unit.javabackend/src/main/java/com/omatheusmesmo/shoppmate/user/entity/User.java
- Added @Setter(AccessLevel.NONE) to audit fields - Prevent manual modification of createdAt and updatedAt - Ensures Spring Data JPA auditing integrity
- Added @Setter(AccessLevel.NONE) to createdAt and updatedAt - Prevent manual modification of audit fields - Added updatable = false for createdAt column - Ensures Spring Data JPA auditing consistency
|
Create a service to abstract this and then do a squash commit. |
|
Hi @matheusandre1, I wanted to clarify the abstraction suggestion before making changes. Since Would you prefer:
I want to make sure the implementation aligns with your intended design before updating the PR. |
|
Updates are repeated, in the case of design and implementation, it depends on what you do, it doesn't need to be anything complex, my review is only for code repetition. |
|
Hi @matheusandre1, thanks for the clarification. I reviewed the implementation again and wanted to confirm I understood your feedback correctly. I kept From your comment about repeated updates/code repetition, are you referring to other duplicated parts (for example common auditing or soft-delete related logic across I just want to make sure the next update aligns with your expectation before I refactor further. |
Changes made
Closes: #23
Enabled Spring Data JPA auditing
Added
@EnableJpaAuditinginShoppMateApplicationAdded auditing annotations to
BaseAuditableEntityAdded auditing support to
DomainEntityImplemented soft delete using
@SQLDeleteand@WhereApplied soft delete to:
This improves entity lifecycle tracking and prevents permanent deletion.
Summary by CodeRabbit