LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 823 min read

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.

pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Product.java
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int price;
// getters and setters omitted
}
ProductRepository.java
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByPriceGreaterThan(int price);
}
What You Get for Free

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.

pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
ProductJdbcRepository.java
@Repository
public 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
);
}
}
Result

Click Run to see what this code prints.

JPA vs JDBC

Aspectstarter-data-jpastarter-jdbc
Abstraction levelHigh — entities and repositories, SQL mostly generatedLow — you write SQL directly
Control over queriesLess direct, more "magic"Full control over exact SQL run
BoilerplateVery little — save()/findAll() come for freeA bit more — mapping rows manually
Best forStandard CRUD-heavy applicationsPerformance-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.

pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
ProductRepository.java — annotate it, that is it
@RepositoryRestResource(path = "products")
public interface ProductRepository extends JpaRepository<Product, Long> {
}
Endpoints Generated Automatically

Click Run to see what this code prints.

Zero Controller Code

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

Avoid These 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.

Next Lesson →

SQL Database Driver Dependencies