Creates JPA entities following best practices.
Creates JPA entities with TSID/UUID keys, value objects, and audit fields following Spring Boot best practices. Triggers when you need to model domain entities with proper JPA annotations, validation, and optimistic locking.
/plugin marketplace add sivaprasadreddy/sivalabs-marketplace/plugin install spring-boot-dev@sivalabs-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
The following are key principles to follow while creating JPA entities:
@EmbeddedId annotation@Enumerated(EnumType.STRING) annotation@Embedded and @AttributeOverrides@VersionBaseEntity for audit fields(createdAt, updatedAt) and extend all entities from itTo use TSID, add the following dependency:
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-71</artifactId>
<version>3.14.1</version>
</dependency>
Now you can use TSID to generate IDs as follows:
import io.hypersistence.tsid.TSID;
public class IdGenerator {
private IdGenerator() {}
public static String generateString() {
return TSID.Factory.getTsid().toString();
}
public static Long generateLong() {
return TSID.Factory.getTsid().toLong();
}
}
public record EventId(String id) {
public EventId {
if (id == null || id.trim().isBlank()) {
throw new IllegalArgumentException("Event id cannot be null or empty");
}
}
public static EventId of(String id) {
return new EventId(id);
}
public static EventId generate() {
return new EventId(IdGenerator.generateString());
}
}
File: BaseEntity.java
import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import java.time.Instant;
@MappedSuperclass
public abstract class BaseEntity {
@Column(name = "created_at", nullable = false, updatable = false)
protected Instant createdAt;
@Column(name = "updated_at", nullable = false)
protected Instant updatedAt;
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
}
Create a AssertUtil class with static methods to validate input parameters.
public class AssertUtil {
private AssertUtil() {}
public static <T> T requireNotNull(T obj, String message) {
if (obj == null)
throw new IllegalArgumentException(message);
return obj;
}
}
While Creating a new JPA entity class, extend it from BaseEntity:
import jakarta.persistence.*;
import java.time.Instant;
@Entity
@Table(name = "events")
class EventEntity extends BaseEntity {
@EmbeddedId
@AttributeOverride(name = "id", column = @Column(name = "id", nullable = false))
private EventId id;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "title", column = @Column(name = "title", nullable = false)),
@AttributeOverride(name = "description", column = @Column(name = "description")),
@AttributeOverride(name = "imageUrl", column = @Column(name = "image_url"))
})
private EventDetails details;
@Enumerated(EnumType.STRING)
@Column(name = "event_type", nullable = false)
private EventType type;
//.. other fields
@Version
private int version;
// Protected constructor for JPA
protected EventEntity() {}
// Constructor with all required fields
public EventEntity(EventId id,
EventCode code,
EventDetails details,
Schedule schedule,
EventType type,
//...
EventLocation location) {
this.id = AssertUtil.requireNotNull(id, "Event id cannot be null");
this.code = AssertUtil.requireNotNull(code, "Event code cannot be null");
this.details = AssertUtil.requireNotNull(details, "Event details cannot be null");
this.schedule = AssertUtil.requireNotNull(schedule, "Event schedule cannot be null");
this.type = AssertUtil.requireNotNull(type, "Event type cannot be null");
this.location = AssertUtil.requireNotNull(location, "Event location cannot be null");
//...
}
// Factory method for creating new entities
public static EventEntity createDraft(
EventDetails details,
Schedule schedule,
EventType type,
TicketPrice ticketPrice,
Capacity capacity,
EventLocation location) {
return new EventEntity(
EventId.generate(),
EventCode.generate(),
details,
schedule,
type,
EventStatus.DRAFT,
ticketPrice,
capacity,
location);
}
// Domain logic methods
public boolean hasFreeSeats() {
return capacity == null || capacity.value() == null || capacity.value() > registrationsCount;
}
public boolean isPublished() {
return status == EventStatus.PUBLISHED;
}
// Getters
}
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.