JPA Entities and Repositories

2 minute read

This chapter covers JPA entity annotations in depth and the different repository interfaces Spring Data provides.


Entity Annotations

@Entity                                    // marks as JPA entity
@Table(name = "books",                     // table name
    uniqueConstraints = @UniqueConstraint(columnNames = "isbn"),
    indexes = @Index(columnList = "author"))
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "title", nullable = false, length = 200)
    private String title;

    @Column(nullable = false)
    private String author;

    @Column(unique = true, length = 17)
    private String isbn;

    @Column(precision = 8, scale = 2)
    private BigDecimal price;

    @Enumerated(EnumType.STRING)           // store enum as string
    @Column(length = 20)
    private BookStatus status;

    @Lob                                    // large text
    private String description;

    @Transient                              // NOT persisted
    private int tempCalculation;

    @CreationTimestamp
    @Column(updatable = false)
    private LocalDateTime createdAt;

    @UpdateTimestamp
    private LocalDateTime updatedAt;
}

public enum BookStatus {
    DRAFT, PUBLISHED, OUT_OF_PRINT
}

ID Generation Strategies

Strategy Behavior Best For
IDENTITY DB auto-increment PostgreSQL, MySQL
SEQUENCE DB sequence PostgreSQL (preferred)
TABLE Separate table Portable (slow)
UUID Random UUID Distributed systems
AUTO JPA picks Avoid — unpredictable
// Sequence (best for PostgreSQL)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "book_seq")
@SequenceGenerator(name = "book_seq", sequenceName = "book_sequence", allocationSize = 50)
private Long id;

// UUID
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

Embedded Objects

@Embeddable
public class Address {
    private String street;
    private String city;
    private String state;

    @Column(name = "zip_code")
    private String zipCode;
}

@Entity
public class Publisher {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Embedded
    private Address address;     // columns go in publisher table
}

Repository Hierarchy

Repository (marker interface)
  └── CrudRepository (basic CRUD)
      └── ListCrudRepository (returns List instead of Iterable)
          └── JpaRepository (JPA-specific: flush, batch, pagination)
// Most common — use JpaRepository
public interface BookRepository extends JpaRepository<Book, Long> {
}

// Minimal — CrudRepository
public interface BookRepository extends CrudRepository<Book, Long> {
}

JpaRepository Extra Methods

Method Purpose
findAll(Sort) Sorted results
findAll(Pageable) Paginated + sorted
flush() Force SQL flush
saveAndFlush(entity) Save + immediate flush
saveAll(list) Batch save
deleteAllInBatch() Bulk delete (single SQL)

Derived Query Methods

Spring generates SQL from method names:

public interface BookRepository extends JpaRepository<Book, Long> {

    List<Book> findByAuthor(String author);
    Optional<Book> findByIsbn(String isbn);
    List<Book> findByTitleContainingIgnoreCase(String keyword);
    List<Book> findByPriceBetween(BigDecimal min, BigDecimal max);
    List<Book> findByStatusAndAuthor(BookStatus status, String author);
    List<Book> findByPublishedDateAfter(LocalDate date);
    boolean existsByIsbn(String isbn);
    long countByAuthor(String author);
    List<Book> findTop5ByOrderByPriceDesc();
}
Keyword SQL Example
findBy WHERE findByTitle(title)
Containing LIKE %x% findByTitleContaining("Java")
Between BETWEEN findByPriceBetween(10, 50)
GreaterThan > findByPriceGreaterThan(20)
OrderBy ORDER BY findByAuthorOrderByTitleAsc(author)
Top / First LIMIT findTop5ByOrderByPriceDesc()
IgnoreCase LOWER() findByTitleIgnoreCase("java")

Key Takeaways

  1. @Entity + @Table map classes to database tables.
  2. Use GenerationType.IDENTITY or SEQUENCE — avoid AUTO.
  3. @Enumerated(EnumType.STRING) — always store enums as strings.
  4. JpaRepository gives CRUD, pagination, sorting, and batch operations.
  5. Derived query methods generate SQL from method names — no queries needed.

What’s Next?

Next: CRUD Operations — save, find, update, delete, pagination, and the DTO pattern.

Updated: