Data & Persistence Dependencies
Learn spring-boot-starter-data-jpa for ORM-based persistence, spring-boot-starter-jdbc for direct JDBC access, and spring-boot-starter-data-rest for auto-exposing repositories as REST endpoints.
Introduction
Almost every non-trivial application needs to store and retrieve data. Spring offers more than one way to do this, ranging from full ORM abstraction down to raw SQL, plus a dependency that can expose your data layer as a REST API with almost no extra code.
spring-boot-starter-data-jpa
Use case: object-relational mapping (ORM), where Java objects (entities) are automatically mapped to database rows, and you interact with the database mostly through repository interfaces instead of writing SQL by hand. Under the hood it uses Hibernate as the JPA implementation, plus Spring Data JPA's repository abstraction.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId></dependency>@Entitypublic class Product {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
private String name; private int price;
// getters and setters omitted}public interface ProductRepository extends JpaRepository<Product, Long> { List<Product> findByPriceGreaterThan(int price);}Click Run to see what this code prints.
Notice `findByPriceGreaterThan` was never implemented — Spring Data JPA parses the method name itself and generates the correct SQL query automatically, a feature called "derived query methods."
spring-boot-starter-jdbc
Use case: direct, lower-level database access when you want full control over your SQL and do not need (or want) the overhead of a full ORM. It provides `JdbcTemplate`, which handles connection management and boilerplate for you while still letting you write raw SQL.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId></dependency>@Repositorypublic class ProductJdbcRepository {
private final JdbcTemplate jdbcTemplate;
public ProductJdbcRepository(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; }
public List<Product> findExpensiveProducts(int minPrice) { return jdbcTemplate.query( "SELECT id, name, price FROM product WHERE price > ?", (rs, rowNum) -> new Product(rs.getLong("id"), rs.getString("name"), rs.getInt("price")), minPrice ); }}Click Run to see what this code prints.
JPA vs JDBC
| Aspect | starter-data-jpa | starter-jdbc |
|---|---|---|
| Abstraction level | High — entities and repositories, SQL mostly generated | Low — you write SQL directly |
| Control over queries | Less direct, more "magic" | Full control over exact SQL run |
| Boilerplate | Very little — save()/findAll() come for free | A bit more — mapping rows manually |
| Best for | Standard CRUD-heavy applications | Performance-critical or complex custom queries |
spring-boot-starter-data-rest
Use case: instantly exposing your Spring Data JPA repositories as fully working, hypermedia-driven REST endpoints, without writing a single `@RestController`. It is ideal for admin tools, internal APIs, or rapid prototypes where you want CRUD endpoints immediately.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId></dependency>@RepositoryRestResource(path = "products")public interface ProductRepository extends JpaRepository<Product, Long> {}Click Run to see what this code prints.
No @RestController, no @GetMapping, no manual serialization — the presence of the JpaRepository interface alone is enough for starter-data-rest to generate a full set of REST endpoints, complete with pagination and HATEOAS links.
Common Mistakes
- Using starter-data-rest for a public-facing production API without adding explicit security — it exposes full CRUD by default, including deletes.
- Reaching for raw JdbcTemplate for standard CRUD when starter-data-jpa would eliminate almost all of that boilerplate.
- Forgetting that derived query method names must follow Spring Data's exact naming conventions, or the query will fail to parse at startup.
Best Practices
- Default to spring-boot-starter-data-jpa for typical business applications; drop to JDBC only for specific, performance-sensitive queries.
- Treat starter-data-rest as a tool for internal tools and admin panels, not as your primary public API surface, unless paired with strict security rules.
- Use @Query with explicit JPQL or native SQL when a derived method name would become too long or unclear to read.
Frequently Asked Questions
Yes, and it is common — use JPA repositories for standard CRUD and drop down to JdbcTemplate (or a native @Query) for a handful of complex, performance-critical queries.
It requires a Spring Data repository (JPA, MongoDB, etc.) to expose — starter-data-jpa is the most common pairing, but it also works with other Spring Data modules.
No, spring-boot-starter-data-jpa already pulls in Hibernate as its default JPA implementation.
Key Takeaways
- spring-boot-starter-data-jpa gives you ORM-based persistence with Hibernate and repository interfaces that need almost no boilerplate.
- spring-boot-starter-jdbc gives you JdbcTemplate for direct, full-control SQL access.
- spring-boot-starter-data-rest can expose a JpaRepository as a full REST API with zero controller code.
Summary
These three dependencies cover the full spectrum from "write no SQL at all" to "write every query yourself," plus a shortcut that skips writing controllers entirely. Every one of them still needs an actual database driver to connect to a real database — which is exactly what the next lesson covers.