Skip to content

GeeCON Prague 2023: Otavio Santana - Mastering Java Persistence: Best Practices for Cloud-Native...

Otavio SantanaMax Million

Cloudgeecon conference47 minOpen on YouTube ↗

GeeCON Prague 2023: Otavio Santana - Mastering Java Persistence: Best Practices for Cloud-Native...

Summary

### Overview In this talk from GeeCON Prague 2023, Otavio Santana explores the critical role of data persistence architectures in software engineering, with a focus on cloud-native Java applications. He highlights that software and persistence decisions are fundamentally governed by trade-offs, where understanding the "why" is more essential than the "how." Emphasizing the importance of domain isolation, data modeling, and performance, Santana details the concept of polyglot persistence across relational and various NoSQL paradigms, as well as the fundamental impedance mismatch between object-oriented programming (OOP) and database storage models.

### Key Topics Santana explains how databases serve as the stateful foundation for otherwise stateless microservices and business opportunities. Rather than treating all data storage needs with a single relational mindset, systems should embrace polyglot persistence by matching requirements with database models: - **Key-Value Stores (e.g., Redis, Amazon S3):** Modeled similarly to hash maps and suited for session management, caching, real-time analytics, and pub/sub. They prioritize horizontal scalability but offer low query flexibility beyond primary keys. - **Wide-Column Databases (e.g., Apache Cassandra):** Feature flexible columns per row, time-to-live (TTL) options, and masterless multi-datacenter replication. Denormalization is favored because write operations are typically cheaper than reads. - **Document Stores (e.g., MongoDB):** Utilize tree structures such as JSON or BSON, supporting embedded documents and secondary indexing for catalogs, content management, and mobile apps. - **Graph Databases (e.g., Neo4j):** Embrace directional, property-rich relationships connecting nodes or vertices, making them suitable for social networks, fraud detection, and recommendation engines.

### Technical Details The presentation delves into the "civil war" and impedance mismatch between application code and database storage. While OOP leverages inheritance, polymorphism, and encapsulation, storage layers rely on specific schemas or structural models, often spending significant performance overhead converting between the two. Santana contrasts data-oriented programming (which separates schema from generic data representation) with OOP/clean code principles (which encapsulate data behind behavior).

To bridge this gap, Santana outlines six core persistence patterns ordered by proximity to the database versus the application domain: 1. **Driver (e.g., JDBC):** Sits closest to the database, providing raw access and high flexibility at the expense of heavy boilerplate and risk of bugs. 2. **Data Mapper (e.g., JPA annotations, JdbcTemplate mapping):** Centralizes object-relational mapping logic to convert database structures into domain entities. 3. **Data Access Object (DAO):** Centralizes imperative data access operations (`insert`, `update`, `delete`) in a structured layer. 4. **Active Record:** Combines domain entity logic and database persistence operations within the entity itself (popularized in frameworks like Quarkus Panache), trading single-responsibility separation for simplicity. 5. **Repository (e.g., Jakarta Data, Spring Data):** Sits closest to the application domain, offering declarative persistence (such as generic `save` semantics) while abstracting lower-level storage mechanisms away from the domain model. 6. **Data Transfer Object (DTO):** Facilitates schema versioning, API exposure, and separation of read/write representations when implementing patterns like CQRS.

### Takeaways - Every persistence choice involves trade-offs between horizontal scalability, operational complexity, and query flexibility. - NoSQL databases must not be treated like relational databases; operations like complex joins should be avoided in favor of access-pattern-driven modeling and denormalization. - Technology isolation is essential: database-specific exceptions or constraints should not leak into business domain logic or user interfaces. - Choosing persistence patterns requires balancing domain abstraction against database proximity, code complexity, and mapping overhead.

Related talks