install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/jpa-entity-creator" ~/.claude/skills/majiayu000-claude-skill-registry-jpa-entity-creator && rm -rf "$T"
manifest:
skills/data/jpa-entity-creator/SKILL.mdsource content
JPA Entity Creator
Instructions
The following are key principles to follow while creating JPA entities:
- Make sure to create the recommended package structure for Spring Boot projects
- Use application generated TSID or UUID as a String for primary keys
- Create a Value Object to represent the primary key and use
annotation@EmbeddedId - Create a protected no-arg constructor for JPA
- Create a public constructor with all required fields
- Validate state and throw exceptions for invalid inputs
- Explicitly define table names for all entities
- Explicitly define column names for all fields
- Use enum types for enum fields and
annotation@Enumerated(EnumType.STRING) - For logically related fields, create a Value Object to represent them
- When using value objects, embed them with
and@Embedded@AttributeOverrides - Add domain methods that operate on entity state
- Use optimistic locking with
@Version - Create
for audit fields(BaseEntity
,createdAt
) and extend all entities from itupdatedAt
IdentityGenerator
To 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(); } }
Value Object for Primary Key
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()); } }
BaseEntity with Auditing Support
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; } }
AssertUtil class to validate input parameters
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; } }
Example JPA Entity Class
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 }