name: spring-boot-entity description: "Creates complete Spring Boot entities with JPA annotations, repositories, services, and REST controllers following project conventions with explicit access modifiers"
Spring Boot Entity Creation Skill
This skill creates complete entity implementations following ActivityTracking project conventions.
When to Use
- Creating a new database entity
- Adding CRUD operations for a new domain object
- Need complete service + repository + controller setup
What This Skill Generates
- JPA Entity - Domain model with proper annotations
- Repository Interface - Spring Data JPA repository
- Service Class - Business logic layer with transactions
- REST Controller - API endpoints
- Unit Tests - Service layer tests
- Integration Tests - Repository tests with Testcontainers
Entity Creation Process
Step 1: Gather Requirements
Ask for:
- Entity name (e.g., "Report", "Category", "Note")
- Fields and types
- Relationships to other entities
- Business rules and validation
- API endpoints needed
Step 2: Generate Entity
package com.ammons.taskactivity.entity;
/**
* Entity representing [description of what this represents].
*
* @author Dean Ammons
* @version 1.0
* @since January 2026
*/
@Entity
@Table(name = "table_name")
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "field_name", nullable = false)
@NotBlank(message = "Field name is required")
private String fieldName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@CreationTimestamp
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "updated_at", nullable = false)
private LocalDateTime updatedAt;
// Getters and setters with explicit access modifiers
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// ... rest of getters/setters
}
Step 3: Generate Repository
package com.ammons.taskactivity.repository;
/**
* Repository interface for MyEntity data access operations.
*
* @author Dean Ammons
* @version 1.0
* @since January 2026
*/
@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
List<MyEntity> findByUserId(Long userId);
Page<MyEntity> findByUserId(Long userId, Pageable pageable);
@Query("SELECT e FROM MyEntity e WHERE e.user.id = :userId AND e.fieldName LIKE %:keyword%")
List<MyEntity> searchByUserAndKeyword(
@Param("userId") Long userId,
@Param("keyword") String keyword
);
}
Step 4: Generate Service
package com.ammons.taskactivity.service;
/**
* Service layer for managing MyEntity business logic.
* Handles CRUD operations, validation, and business rules.
*
* @author Dean Ammons
* @version 1.0
* @since January 2026
*/
@Service
@Transactional
public class MyEntityService {
private final MyEntityRepository repository;
private final UserService userService;
public MyEntityService(MyEntityRepository repository, UserService userService) {
this.repository = repository;
this.userService = userService;
}
/**
* Retrieves all entities for a specific user.
*
* @param userId The user's unique identifier
* @return List of entities belonging to the user
*/
@Transactional(readOnly = true)
public List<MyEntity> findByUserId(Long userId) {
return repository.findByUserId(userId);
}
/**
* Creates or updates an entity.
*
* @param entity The entity to save
* @return The saved entity with generated ID
* @throws ValidationException if validation fails
*/
public MyEntity save(MyEntity entity) {
validateEntity(entity);
return repository.save(entity);
}
/**
* Deletes an entity by ID.
*
* @param id The entity's unique identifier
* @throws ResourceNotFoundException if entity not found
*/
public void deleteById(Long id) {
if (!repository.existsById(id)) {
throw new ResourceNotFoundException("Entity not found with id: " + id);
}
repository.deleteById(id);
}
private void validateEntity(MyEntity entity) {
if (entity.getFieldName() == null || entity.getFieldName().trim().isEmpty()) {
throw new ValidationException("Field name is required");
}
}
}
Step 5: Generate REST Controller
package com.ammons.taskactivity.controller;
/**
* REST API controller for MyEntity operations.
* Provides CRUD endpoints with proper HTTP semantics.
*
* @author Dean Ammons
* @version 1.0
* @since January 2026
*/
@RestController
@RequestMapping("/api/myentities")
@CrossOrigin(origins = "*")
public class MyEntityController {
private final MyEntityService service;
public MyEntityController(MyEntityService service) {
this.service = service;
}
@GetMapping
public ResponseEntity<List<MyEntity>> getAll(Principal principal) {
Long userId = getUserIdFromPrincipal(principal);
List<MyEntity> entities = service.findByUserId(userId);
return ResponseEntity.ok(entities);
}
@GetMapping("/{id}")
public ResponseEntity<MyEntity> getById(@PathVariable Long id) {
return service.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<MyEntity> create(
@Valid @RequestBody MyEntity entity,
Principal principal) {
Long userId = getUserIdFromPrincipal(principal);
entity.setUser(new User(userId));
MyEntity saved = service.save(entity);
return ResponseEntity.status(HttpStatus.CREATED).body(saved);
}
@PutMapping("/{id}")
public ResponseEntity<MyEntity> update(
@PathVariable Long id,
@Valid @RequestBody MyEntity entity) {
return service.findById(id)
.map(existing -> {
entity.setId(id);
MyEntity updated = service.save(entity);
return ResponseEntity.ok(updated);
})
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
try {
service.deleteById(id);
return ResponseEntity.noContent().build();
} catch (ResourceNotFoundException e) {
return ResponseEntity.notFound().build();
}
}
private Long getUserIdFromPrincipal(Principal principal) {
// Extract user ID from JWT principal
return 1L; // Implement based on your auth setup
}
}
Step 6: Generate Tests
/**
* Unit tests for MyEntityService business logic.
*
* @author Dean Ammons
* @version 1.0
* @since January 2026
*/
@ExtendWith(MockitoExtension.class)
class MyEntityServiceTest {
@Mock
private MyEntityRepository repository;
@Mock
private UserService userService;
@InjectMocks
private MyEntityService service;
@Test
@DisplayName("Should save entity successfully")
void shouldSaveEntity() {
// Given
MyEntity entity = MyEntity.builder()
.fieldName("Test")
.build();
when(repository.save(any())).thenReturn(entity);
// When
MyEntity saved = service.save(entity);
// Then
assertNotNull(saved);
verify(repository).save(entity);
}
}
Project Conventions Enforced
✅ Explicit Access Modifiers - Every class, method, field ✅ JavaDoc - File-level with @author, @version, @since ✅ Constructor Injection - No field injection ✅ Validation - Bean Validation annotations ✅ Transactions - @Transactional on service methods ✅ Error Handling - Proper exception types ✅ Testing - Unit + integration tests
Database Migration
After creating entity, remind to:
- Add table to
schema.sqlfor fresh installs - Create migration script for existing databases
- Update production database
CREATE TABLE IF NOT EXISTS my_entities (
id BIGSERIAL PRIMARY KEY,
field_name VARCHAR(255) NOT NULL,
user_id BIGINT NOT NULL REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_my_entities_user_id ON my_entities(user_id);
Angular Service (Optional)
/**
* Service for managing MyEntity operations via REST API.
*
* Author: Dean Ammons
* Date: January 2026
*/
@Injectable({ providedIn: "root" })
export class MyEntityService {
private apiUrl = "/api/myentities";
constructor(private http: HttpClient) {}
getAll(): Observable<MyEntity[]> {
return this.http.get<MyEntity[]>(this.apiUrl);
}
create(entity: MyEntity): Observable<MyEntity> {
return this.http.post<MyEntity>(this.apiUrl, entity);
}
update(id: number, entity: MyEntity): Observable<MyEntity> {
return this.http.put<MyEntity>(`${this.apiUrl}/${id}`, entity);
}
delete(id: number): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/${id}`);
}
}
Checklist
- Entity has explicit access modifiers on all members
- JavaDoc includes @author, @version, @since
- Repository uses constructor injection
- Service has @Transactional annotations
- Controller has proper HTTP status codes
- Validation annotations on entity fields
- Unit tests for service logic
- Integration tests for repository
- Database migration script created
- Memory banks updated if architectural change
Memory Bank References
- Check
ai/java-conventions.mdfor coding standards - Check
ai/common-patterns.mdfor templates - Check
ai/architecture-patterns.mdfor entity patterns
chat Comments (0)
Sign in to join the discussion and leave a comment.
Skill Details
GitHub Stars
0
GitHub Forks
0
Created
Jan 2026
Last Updated
5 months ago
tools
tools architecture patterns
Related Skills
Build your own?
Join 12,000+ developers contributing to the Claude ecosystem.
No comments yet. Be the first to share your thoughts!