E-Book, Englisch, 1043 Seiten
Leonard Spring Boot Persistence Best Practices
1. ed
ISBN: 978-1-4842-5626-8
Verlag: Apress
Format: PDF
Kopierschutz: 1 - PDF Watermark
Optimize Java Persistence Performance in Spring Boot Applications
E-Book, Englisch, 1043 Seiten
ISBN: 978-1-4842-5626-8
Verlag: Apress
Format: PDF
Kopierschutz: 1 - PDF Watermark
This book is a collection of developer code recipes and best practices for persisting data using Spring, particularly Spring Boot. The book is structured around practical recipes, where each recipe discusses a performance case or performance-related case, and almost every recipe has one or more applications. Mainly, when we try to accomplish something (e.g., read some data from the database), there are several approaches to do it, and, in order to choose the best way, you have to know the implied trades-off from a performance perspective. You'll see that in the end, all these penalties slow down the application. Besides presenting the arguments that favor a certain choice, the application is written in Spring Boot style which is quite different than plain Hibernate.
Persistence is an important set of techniques and technologies for accessing and using data, and this book demonstrates that data is mobile regardless of specific applications and contexts. In Java development, persistence is a key factor in enterprise, ecommerce, cloud and other transaction-oriented applications.
After reading and using this book, you'll have the fundamentals to apply these persistence solutions into your own mission-critical enterprise Java applications that you build using Spring.
What You Will Learn
Shape *-to-many associations for best performances
Effectively exploit Spring Projections (DTO)
Learn best practices for batching inserts, updates and deletes
Effectively fetch parent and association in a single SELECT
Learn how to inspect Persistent Context content
Dissect pagination techniques (offset and keyset)
Handle queries, locking, schemas, Hibernate types, and more
Who This Book Is For
Any Spring and Spring Boot developer that wants to squeeze the persistence layer performances.
Anghel Leonard is a Chief Technology Strategist with 20+ years of experience in the Java ecosystem. In daily work, he is focused on architecting and developing Java distributed applications that empower robust architectures, clean code, and high-performance. Also passionate about coaching, mentoring and technical leadership. He is the author of several books, videos and dozens of articles related to Java technologies.
Autoren/Hrsg.
Weitere Infos & Material
1;Table of Contents;5
2;About the Author;23
3;About the Technical Reviewer;24
4;Introduction;25
5;Chapter 1: Associations;29
5.1;Item 1: How to Effectively Shape the @OneToMany Association;29
5.1.1;Always Cascade from Parent-Side to Child-Side;30
5.1.2;Don’t Forget to Set mappedBy on the Parent-Side;30
5.1.3;Set orphanRemoval on the Parent-Side;31
5.1.4;Keep Both Sides of the Association in Sync;31
5.1.5;Override equals() and hashCode();32
5.1.6;Use Lazy Fetching on Both Sides of the Association;33
5.1.7;Pay Attention to How toString() Is Overridden;33
5.1.8;Use @JoinColumn to Specify the Join Column Name;33
5.1.9;Author and Book Samples;34
5.2;Item 2: Why You Should Avoid the Unidirectional @OneToMany Association;36
5.2.1;Regular Unidirectional @OneToMany;38
5.2.1.1;Persisting an Author and Their Books;38
5.2.1.2;Persisting a New Book of an Existing Author;40
5.2.1.3;Deleting the Last book;41
5.2.1.4;Deleting the First Book;42
5.2.2;Using @OrderColumn;43
5.2.2.1;Persist the Author and Books;44
5.2.2.2;Persist a New Book of an Existing Author;45
5.2.2.3;Delete the Last Book;45
5.2.2.4;Delete the First Book;46
5.2.3;Using @JoinColumn;47
5.2.3.1;Persist the Author and Books;47
5.2.3.2;Persist a New Book of an Existing Author;48
5.2.3.3;Delete the Last Book;49
5.2.3.4;Delete the First Book;49
5.3;Item 3: How Efficient Is the Unidirectional @ManyToOne;50
5.3.1;Adding a New Book to a Certain Author;52
5.3.2;Fetching All Books of an Author;54
5.3.3;Paging the Books of an Author;55
5.3.4;Fetching All Books of an Author and Adding a New Book;56
5.3.5;Fetching all Books of an Author and Deleting a Book;57
5.4;Item 4: How to Effectively Shape the @ManyToMany Association;58
5.4.1;Choose the Owner of the Relationship;59
5.4.2;Always Use Set not List;59
5.4.3;Keep Both Sides of the Association in Sync;59
5.4.4;Avoid CascadeType.ALL and CascadeType.REMOVE;59
5.4.5;Setting Up the Join Table;60
5.4.6;Using Lazy Fetching on Both Sides of the Association;60
5.4.7;Override equals() and hashCode();60
5.4.8;Pay Attention to How toString() Is Overridden;60
5.4.9;Author and Book Samples;60
5.5;Item 5: Why Set Is Better than List in @ManyToMany;64
5.5.1;Using List;64
5.5.2;Using Set;66
5.5.2.1;Preserving the Order of the Result Set;67
5.5.2.2;Using @OrderBy;68
5.6;Item 6: Why and When to Avoid Removing Child Entities with CascadeType.Remove and orphanRemoval=true;69
5.6.1;Deleting Authors that Are Already Loaded in the Persistence Context;73
5.6.2;One Author Has Already Been Loaded in the Persistence Context;73
5.6.3;More Authors Have Been Loaded in the Persistence Context;74
5.6.4;One Author and His Associated Books Have Been Loaded in the Persistence Context;76
5.6.5;Deleting When the Author and Books that Should Be Deleted Are Not Loaded in the Persistence Context;78
5.7;Item 7: How to Fetch Associations via JPA Entity Graphs;80
5.7.1;Defining an Entity Graph via @NamedEntityGraph;81
5.7.1.1;Overriding a Query Method;82
5.7.1.2;Using the Query Builder Mechanism;83
5.7.1.3;Using Specification;84
5.7.1.4;Using @Query and JPQL;85
5.7.2;Ad Hoc Entity Graphs;87
5.7.3;Defining an Entity Graph via EntityManager;89
5.8;Item 8: How to Fetch Associations via Entity Sub-Graphs;90
5.8.1;Using @NamedEntityGraph and @NamedSubgraph;92
5.8.2;Using the Dot Notation (.) in Ad Hoc Entity Graphs;95
5.8.3;Defining an Entity Sub-Graph via EntityManager;98
5.9;Item 9: How to Handle Entity Graphs and Basic Attributes;98
5.10;Item 10: How to Filter Associations via a Hibernate-Specific @Where Annotation;103
5.11;Item 11: How to Optimize Unidirectional/Bidirectional @OneToOne via @MapsId;107
5.11.1;Regular Unidirectional @OneToOne;107
5.11.2;Regular Bidirectional @OneToOne;110
5.11.3;@MapsId to the Rescue of @OneToOne;112
5.12;Item 12: How to Validate that Only One Association Is Non-Null;115
5.12.1;Testing Time;117
6;Chapter 2: Entities;119
6.1;Item 13: How to Adopt a Fluent API Style in Entities;119
6.1.1;Fluent-Style via Entity Setters;120
6.1.2;Fluent-Style via Additional Methods;123
6.2;Item 14: How to Populate a Child-Side Parent Association via a Hibernate-Specific Proxy;126
6.2.1;Using findById();127
6.2.2;Using getOne();128
6.3;Item 15: How to Use Java 8 Optional in Persistence Layer;129
6.3.1;Optional in Entities;129
6.3.2;Optional in Repositories;131
6.4;Item 16: How to Write Immutable Entities;132
6.5;Item 17: How to Clone Entities;134
6.5.1;Cloning the Parent and Associating the Books;135
6.5.2;Cloning the Parent and the Books;138
6.5.3;Joining These Cases;141
6.6;Item 18: Why and How to Activate Dirty Tracking;142
6.7;Item 19: How to Map a Boolean to a Yes/No;145
6.8;Item 20: The Best Way to Publish Domain Events from Aggregate Roots;147
6.8.1;Synchronous Execution;151
6.8.2;Asynchronous Execution;157
7;Chapter 3: Fetching;162
7.1;Item 21: How to Use Direct Fetching;162
7.1.1;Direct Fetching via Spring Data;163
7.1.2;Fetching via EntityManager;164
7.1.3;Fetching via Hibernate-Specific Session;164
7.1.4;Direct Fetching and Session-Level Repeatable-Reads;166
7.1.5;Direct Fetching Multiple Entities by ID;173
7.2;Item 22: Why Use Read-Only Entities Whenever You Plan to Propagate Changes to the Database in a Future Persistence Context;175
7.2.1;Load Author in Read-Write Mode;175
7.2.2;Load Author in Read-Only Mode;176
7.2.3;Update the Author;177
7.3;Item 23: How to Lazy Load the Entity Attributes via Hibernate Bytecode Enhancement;178
7.3.1;Enabling Lazy Loading of Attributes;179
7.3.2;Attribute Lazy Loading and N+1;182
7.3.3;Attribute Lazy Loading and Lazy Initialization Exceptions;184
7.3.3.1;Setting Explicit Default Values for Lazy Loaded Attributes;186
7.3.3.1.1;Providing a Custom Jackson Filter;187
7.4;Item 24: How to Lazy Load the Entity Attributes via Subentities;190
7.5;Item 25: How to Fetch DTO via Spring Projections;194
7.5.1;JPA Named (Native) Queries Can Be Combined with Spring Projections;199
7.5.2;Class-Based Projections;203
7.5.3;How to Reuse a Spring Projection;204
7.5.4;How to Use Dynamic Spring Projections;206
7.6;Item 26: How to Add an Entity in a Spring Projection;208
7.6.1;Materialized Association;208
7.6.2;Not Materialized Association;209
7.7;Item 27: How to Enrich Spring Projections with Virtual Properties That Are/Aren’t Part of Entities;211
7.8;Item 28: How to Efficiently Fetch Spring Projection Including *-to-One Associations;213
7.8.1;Using Nested Closed Projections;214
7.8.2;Using a Simple Closed Projection;217
7.8.3;Using a Simple Open Projection;219
7.9;Item 29: Why to Pay Attention to Spring Projections that Include Associated Collections;222
7.9.1;Using Nested Spring Closed Projection;222
7.9.1.1;Use the Query Builder Mechanism;223
7.9.1.2;Use an Explicit JPQL;226
7.9.1.3;Use JPA JOIN FETCH;229
7.9.2;Using a Simple Closed Projection;233
7.9.3;Transform List in DTO;235
7.10;Item 30: How to Fetch All Entity Attributes via Spring Projection;240
7.10.1;Using the Query Builder Mechanism;242
7.10.2;Using JPQL and @Query;242
7.10.3;Using JPQL with an Explicit List of Columns and @Query;244
7.10.4;Using a Native Query and @Query;245
7.11;Item 31: How to Fetch DTO via Constructor Expression;246
7.12;Item 32: Why You Should Avoid Fetching Entities in DTO via the Constructor Expression;250
7.13;Item 33: How to Fetch DTO via a JPA Tuple;253
7.14;Item 34: How to Fetch DTO via @SqlResultSetMapping and @NamedNativeQuery;256
7.14.1;Scalar Mappings;257
7.14.2;Constructor Mapping;258
7.14.3;Entity Mapping;260
7.15;Item 35: How to Fetch DTO via ResultTransformer;260
7.16;Item 36: How to Fetch DTO via a custom ResultTransformer;265
7.17;Item 37: How to Map an Entity to a Query via @Subselect;270
7.18;Item 38: How to Fetch DTO via Blaze-Persistence Entity Views;274
7.19;Item 39: How to Effectively Fetch Parent and Association in One SELECT;278
7.20;Item 40: How to Decide Between JOIN and JOIN FETCH;283
7.20.1;Fetch All Authors and Their Books that Are More Expensive than the Given Price;284
7.20.2;How JOIN FETCH Will Act;285
7.20.3;How JOIN Will Act;286
7.20.4;Fetch All Books and their Authors;288
7.20.5;How JOIN FETCH Will Act;289
7.20.6;How JOIN Will Act;290
7.21;Item 41: How to Fetch All Left Entities;292
7.22;Item 42: How to Fetch DTO from Unrelated Entities;294
7.23;Item 43: How to Write JOIN Statements;295
7.23.1;INNER JOIN;297
7.23.2;LEFT JOIN;298
7.23.3;RIGHT JOIN;299
7.23.4;CROSS JOIN;300
7.23.5;FULL JOIN;302
7.23.6;Simulate a FULL JOIN in MySQL;303
7.24;Item 44: How to Paginate JOINs;304
7.24.1;The DENSE_RANK() Window Function to the Rescue;310
7.25;Item 45: How to Stream the Result Set (in MySQL) and How to Use the Streamable Utility;314
7.25.1;Stream the Result Set (in MySQL);314
7.25.2;Do Not Confuse Stream with the Streamable Utility;315
7.25.3;Don’t Fetch More Columns than Needed Just to Drop a Part of them via map();317
7.25.4;Don’t Fetch More Rows than Needed Just to Drop a Part of Them via filter();317
7.25.5;Pay Attention to Concatenating Streamable via and();318
7.25.6;How to Return Custom Streamable Wrapper Types;320
8;Chapter 4: Batching;323
8.1;Item 46: How to Batch Inserts in Spring Boot Style;323
8.1.1;Enabling Batching and Preparing the JDBC URL;323
8.1.1.1;Setting the Batch Size;323
8.1.1.2;Batching Optimizations for MySQL;324
8.1.2;Preparing the Entities for Batching Inserts;326
8.1.3;Identify and Avoid the Built-In saveAll(Iterable entities) Drawbacks;328
8.1.4;Custom Implementation Is the Way to Go;329
8.1.4.1;Writing the BatchRepository Contract;330
8.1.4.2;Writing the BatchRepository Implementation;330
8.1.4.3;Setting BatchRepositoryImpl as the Base Class;333
8.1.5;Testing Time;333
8.2;Item 47: How to Optimize Batch Inserts of Parent-Child Relationships;335
8.2.1;Ordering Inserts;336
8.3;Item 48: How to Control Batch Size at the Session Level;338
8.4;Item 49: How to Fork-Join JDBC Batching;339
8.4.1;Fork-Join Batching;340
8.5;Item 50: Batching Entities via CompletableFuture;344
8.6;Item 51: How to Efficiently Batch Updates;348
8.6.1;Versioned Entities;349
8.6.2;Batch Updates of Parent-Child Relationships;349
8.6.3;Bulk Updates;350
8.7;Item 52: How to Efficiently Batch Deletes (No Associations);352
8.7.1;Delete via the Built-In deleteAllInBatch() Method;354
8.7.2;Delete via the Built-In deleteInBatch(Iterable entities);355
8.7.3;Delete via the Built-In deleteAll() Methods;357
8.7.4;Delete via the Built-In delete(T entity) Method;359
8.8;Item 53: How to Efficiently Batch Deletes (with Associations);360
8.8.1;Relying on orphanRemoval = true;361
8.8.1.1;Delete via the Built-In deleteAllInBatch() Method;362
8.8.2;Delete via the Built-In deleteInBatch(Iterable entities);363
8.8.3;Delete via the Built-In deleteAll(Iterable entities) and delete(T entity) Methods;364
8.8.4;Relying on SQL, ON DELETE CASCADE;368
8.8.5;Delete via the Built-In deleteAllInBatch() Method;369
8.8.6;Delete via the Built-In deleteInBatch(Iterable entities);369
8.8.7;Delete via the Built-In deleteAll(Iterable entities) and delete(T entity) Methods;370
8.9;Item 54: How to Fetch Association in Batches;372
8.9.1;@BatchSize at the Collection-Level;372
8.9.2;@BatchSize at Class/Entity-Level;375
8.10;Item 55: Why to Avoid PostgreSQL (BIG)SERIAL in Batching Inserts via Hibernate;378
8.10.1;Optimize the Identifier-Fetching Process;379
8.10.2;Optimize Batching via reWriteBatchedInserts;380
9;Chapter 5: Collections;382
9.1;Item 56: How to JOIN FETCH an @ElementCollection Collection;382
9.2;Item 57: How to DTO an @ElementCollection;384
9.3;Item 58: Why and When to Use @OrderColumn with @ElementCollection;387
9.3.1;Optimizing @ElementCollection via @OrderColumn;391
9.3.1.1;Adding One Book to the Beginning of the Current Cart;392
9.3.1.2;Adding One Book to the End of the Current Cart;393
9.3.1.3;Adding One Book to the Middle of the Current Cart;394
9.3.1.4;Removing the First Book from the Current Cart;395
9.3.1.5;Removing the Last Book from the Current Cart;396
9.3.1.6;Removing One Book from the Middle of the Current Cart;396
9.4;Item 59: How to Merge Entity Collections;398
9.4.1;Merging the Detached Collection;402
9.4.2;Testing Time;405
10;Chapter 6: Connections and Transactions;407
10.1;Item 60: How to Delay Connection Acquisition Until It’s Really Needed;407
10.2;Item 61: How @Transactional(readOnly=true) Really Works;410
10.3;Item 62: Why Spring Ignores @Transactional;420
10.4;Item 63: How to Set and Check that Transaction Timeout and Rollback at Expiration Work as Expected;424
10.4.1;Setting Transaction and Query Timeouts;427
10.4.2;Check That a Transaction Was Rolled Back;428
10.5;Item 64: Why and How to Use @Transactional in a Repository Interface;428
10.5.1;Does Query-methods listed in an interface repository run by default in a transactional-context?;429
10.5.2;Okay, So All I Have to Do Is Add @Transactional at the Service-Method Level, Right?;434
10.5.3;But, Generally Speaking, Is this Approach Always Enough?;438
10.5.4;I Know! Let’s Move @Transactional in the Repository Interface!;440
10.5.5;But What If I Want to Call More Query-Methods in the Service-Method? Do I Lose ACID?;441
10.5.6;So, If I Delay the Connection Acquisition then I Can Avoid @Transactional in Repository Interfaces?;446
10.5.6.1;Case 1;447
10.5.6.2;Case 2;448
10.5.7;Three Simple and Common Scenarios;450
10.5.7.1;Roll Back a Service-Method at Exception Thrown by the Code that Doesn't Interact with the Database;450
10.5.7.2;Cascading and @Transactional;452
10.5.7.3;Select ? Modify ? Save and an Interleaved Long-Running Task;452
11;Chapter 7: Identifiers;457
11.1;Item 65: Why to Avoid the Hibernate 5 AUTO Generator Type in MySQL;457
11.2;Item 66: How to Optimize the Generation of Sequence Identifiers via the hi/lo Algorithm;459
11.2.1;Dealing with External Systems;464
11.3;Item 67: How to Optimize the Generation of Sequence Identifiers via Pooled (-lo) Algorithms;465
11.3.1;The Pooled Algorithm;466
11.3.1.1;Dealing with External Systems;468
11.3.2;The Pooled-Lo Algorithm;469
11.3.2.1;Dealing with External Systems;471
11.4;Item 68: How to Correctly Override equals() and hashCode();472
11.4.1;Building the Unit Test;472
11.4.2;Best Approaches for Overriding equals() and hashCode();475
11.4.2.1;Using a Business Key;475
11.4.2.2;Using @NaturalId;477
11.4.2.3;Manually Assigned Identifier;478
11.4.2.4;Database-Generated Identifiers;480
11.4.3;Approaches for Overriding equals() and hashCode() that Must Be Avoided;482
11.4.3.1;Default Implementation (JVM);482
11.4.3.2;Database-Generated Identifiers;483
11.4.3.3;Lombok @EqualsAndHashCode;485
11.5;Item 69: How to Use Hibernate-Specific @NaturalId in Spring Style;487
11.5.1;Testing Time;491
11.5.2;Compound Natural ID;492
11.6;Item 70: How to Use Hibernate-Specific @NaturalId and Skip the Entity Identifier Retrieval;495
11.6.1;Using @NaturalIdCache Solely;496
11.6.2;Using @NaturalIdCache and @Cache;498
11.7;Item 71: How to Define an Association that References a @NaturalId Column;501
11.7.1;Testing Time;502
11.8;Item 72: How to Obtain Auto-Generated Keys;503
11.8.1;Retrieve Auto-Generated Keys via getId();504
11.8.2;Retrieve Auto-Generated Keys via JdbcTemplate;504
11.8.3;Retrieve Auto-Generated Keys via SimpleJdbcInsert;506
11.9;Item 73: How to Generate Custom Sequence IDs;506
11.10;Item 74: How to Efficiently Implement a Composite Primary Key;508
11.10.1;Composite key via @Embeddable and @EmbeddedId;510
11.10.1.1;Testing Time;516
11.10.1.2;Persist an Author and Three Books;516
11.10.1.3;Find an Author by Name;518
11.10.1.4;Remove a Book of an Author;518
11.10.1.5;Remove an Author;520
11.10.2;Composite key via @IdClass;521
11.10.3;How About the Universally Unique Identifier (UUID)?;522
11.10.4;Generate UUID via GenerationType.AUTO;523
11.10.5;Manually Assigned UUID;525
11.10.6;Hibernate-Specific uuid2;526
11.11;Item 75: How to Define a Relationship in a Composite Key;527
11.11.1;Testing Time;532
11.11.2;Persist a Publisher;532
11.11.3;Persist Two Authors;533
11.11.4;Find an Author by Name;536
11.11.5;Remove a Book of an Author;537
11.11.6;Remove an Author;538
11.12;Item 76: How to Use an Entity for the Junction Table;540
11.12.1;Define a Composite Primary Key for the Junction Table;540
11.12.2;Define an Entity for the Junction Table;542
11.12.3;Plug In the Author and Book;544
12;Chapter 8: Calculating Properties;547
12.1;Item 77: How to Map Calculated Non-Persistent Properties;547
12.1.1;JPA Quick Approach;547
12.1.2;JPA @PostLoad;548
12.1.3;Hibernate-specific @Formula;549
12.2;Item 78: How to Map Calculated Persistent Properties via @Generated;550
12.2.1;Hibernate-Specific @Generated;551
12.2.1.1;Formula via columnDefinition Element;552
12.2.1.2;Formula via CREATE TABLE;553
12.2.1.3;Testing Time;554
12.3;Item 79: How to Use SQL Functions with Multiple Parameters in JPQL Queries;555
12.3.1;Function in the SELECT Part;556
12.3.2;Function in the WHERE Part;558
12.4;Item 80: How to Map @ManyToOne Relationship to an SQL Query Via @JoinFormula;560
13;Chapter 9: Monitoring;564
13.1;Item 81: Why and How to Count and Assert SQL Statements;564
13.2;Item 82: How to Log the Binding and Extracted Parameters of a Prepared Statement;569
13.2.1;TRACE;569
13.2.2;Log4j 2;571
13.2.3;MySQL and profileSQL=true;572
13.3;Item 83: How to Log Query Details;572
13.3.1;Via DataSource-Proxy;572
13.3.2;Via log4jdbc;573
13.3.3;Via P6spy;574
13.4;Item 84: How to Log Slow Queries with Threshold;575
13.5;Item 85: Log Transactions and Query-Methods Details;577
13.5.1;Log Transactions Details;577
13.5.2;Take Control via Transaction Callbacks;577
13.5.3;Log Query-Methods Execution Time;580
14;Chapter 10: Configuring DataSource and Connection Pool;583
14.1;Item 86: How to Customize HikariCP Settings;583
14.1.1;Tuning HikariCP Parameters via application.properties;584
14.1.2;Tuning HikariCP Parameters via application.properties and DataSourceBuilder;585
14.1.3;Tuning HikariCP Parameters via DataSourceBuilder;586
14.1.4;Tuning Other Connection Pools;587
14.2;Item 87: How to Configure Two Data Sources with Two Connection Pools;588
14.2.1;Testing Time;594
15;Chapter 11: Audit;596
15.1;Item 88: How to Track the Creation and Modification Times and Entity Users;596
15.1.1;Rely on Spring Data JPA Auditing;597
15.1.2;Relying on Hibernate Support;600
15.1.2.1;The created and lastModified Fields;600
15.1.3;The createdBy and lastModifiedBy Fields;601
15.1.4;Testing Time;604
15.2;Item 89: How to Enable Hibernate-Specific Envers Auditing;605
15.2.1;Auditing Entities;606
15.2.2;Schema Generation;607
15.2.3;Querying the Entity Snapshots;609
15.2.3.1;ValidityAuditStrategy Audit Logging Strategy;610
15.3;Item 90: How to Inspect the Persistence Context;612
15.4;Item 91: How to Extract Table Metadata;617
16;Chapter 12: Schemas;622
16.1;Item 92: How to Set Up Flyway in Spring Boot;622
16.1.1;Quickest Flyway Setup (MySQL and PostgreSQL);622
16.1.2;Instruct Flyway to Create the Database;623
16.1.2.1;MySQL;624
16.1.2.2;PostgreSQL;624
16.1.3;Set Up Flyway via @FlywayDataSource;626
16.1.4;Flyway and Multiple Schemas;627
16.2;Item 93: How to Generate Two Databases via schema-*.sql and Match Entities to Them;627
17;Chapter 13: Pagination;630
17.1;Item 94: When and Why Offset Pagination May Become a Performance Penalty;630
17.1.1;Index Scan in Offset and Keyset;630
17.1.2;Offset Pagination Pros and Cons;631
17.1.3;Spring Boot Offset Pagination;633
17.2;Item 95: How to Optimize Offset Pagination with COUNT(*) OVER and Page;640
17.2.1;COUNT(*) OVER( ) Windowed Aggregate;640
17.2.1.1;Pages as Page;640
17.2.1.2;Pages as Page;645
17.2.1.2.1;Use a Dedicated Property;645
17.3;Item 96: How to Optimize Offset Pagination with SELECT COUNT subquery and Page;649
17.3.1;SELECT COUNT Subquery;649
17.3.1.1;Pages as Page;649
17.3.1.2;Pages as Page;654
17.3.1.2.1;Use an Extra Property;654
17.4;Item 97: How to Use JOIN FETCH and Pageable;657
17.5;Item 98: How to Fix HHH000104;661
17.5.1;Fetching Managed Entities;662
17.5.1.1;Fetching Page;662
17.5.1.2;Fetching Slice;667
17.5.1.3;Fetching List;670
17.6;Item 99: How to Implement Slice findAll( );672
17.6.1;Quick Implementation;673
17.6.1.1;Fetching Slice;673
17.6.1.2;Fetching Slice;675
17.6.2;Implementation of Slice findAll(Pageable pageable);677
17.7;Item 100: How to Implement Keyset Pagination;679
17.8;Item 101: How to Add a Next Page Button to Keyset Pagination;683
17.9;Item 102: How to Implement Pagination via ROW_NUMBER( );686
18;Chapter 14: Queries;688
18.1;Item 103: How to Optimize SELECT DISTINCT via Hibernate-Specific HINT_PASS_DISTINCT_THROUGH;688
18.2;Item 104: How to Set Up JPA Callbacks;694
18.2.1;Separate Listener Class via @EntityListeners;696
18.3;Item 105: How to Use Spring Data Query Builder to limit the Result Set Size and to Count and Delete Derived Queries;698
18.3.1;Limiting the Result Set Size;698
18.3.2;Count and Delete Derived Queries;703
18.3.2.1;Derived Count Queries;703
18.3.2.2;Derived Delete Queries;703
18.4;Item 106: Why You Should Avoid Time-Consuming Tasks in Post-Commits;704
18.5;Item 107: How to Avoid Redundant save() Calls;706
18.6;Item 108: Why and How to Prevent N+1 Issues;708
18.6.1;Hibernate-Specific @Fetch(FetchMode.JOIN) and N+1;710
18.6.1.1;Using JOIN FETCH Instead of FetchMode.JOIN;713
18.6.1.2;Using Entity Graphs Instead of FetchMode.JOIN;714
18.7;Item 109: How to Use Hibernate-Specific Soft Deletes Support;715
18.7.1;Hibernate Soft Deletes;717
18.7.1.1;Testing Time;719
18.7.1.1.1;Deleting an Author;719
18.7.1.1.2;Deleting a Book;721
18.7.1.1.3;Restoring an Author;722
18.7.1.1.4;Restoring a Book;723
18.7.1.2;Useful Queries;723
18.7.1.3;Update the Deleted Property in the Current Persistence Context;724
18.8;Item 110: Why and How to Avoid the OSIV Anti-Pattern;725
18.8.1;Hibernate5Module;729
18.8.1.1;Testing Time;730
18.8.2;Explicitly (Manually) Initializing the Unfetched Lazy Properties;732
18.8.2.1;Testing Time;732
18.8.3;How About the Hibernate-Specific hibernate.enable_lazy_load_no_trans;734
18.9;Item 111: How to Store Date/Time in UTC Time Zone (MySQL);735
18.10;Item 112: How to Shuffle Small Result Sets via ORDER BY RAND();738
18.11;Item 113: How to Use Subqueries in the WHERE/HAVING Clause;739
18.12;Item 114: How to Call a Stored Procedure;743
18.12.1;Calling a Stored Procedure that Returns a Value (Scalar Data Types);744
18.12.2;Calling a Stored Procedure that Returns a Result Set;746
18.12.2.1;Calling a Stored Procedure via JdbcTemplate;746
18.12.2.1.1;Call the Stored Procedure that Returns the Nickname and Age Columns of Authors of the Given Genre (Can Be One or Multiple Authors);747
18.12.2.1.2;Call the Stored Procedure that Returns All Authors of the Given Genre;748
18.12.2.2;Calling a Stored Procedure via a Native Query;749
18.12.2.2.1;Call the Stored Procedure that Returns the Nickname and Age Columns of Authors of the Given Genre (Can Be One or Multiple Authors);749
18.12.2.2.2;Call the Stored Procedure that Returns All Authors of the Given Genre;750
18.12.2.3;Calling a Stored Procedure via EntityManager;751
18.12.2.3.1;Call the Stored Procedure that Returns the Nickname and Age Columns of Authors of the Given Genre (Can Be One or Multiple Authors);751
18.12.2.3.2;Call the Stored Procedure that Returns All Authors of the Given Genre;754
18.13;Item 115: How to Unproxy a Proxy;757
18.13.1;What Is a Proxy Object?;757
18.13.2;An Entity Object and a Proxy Object Are Not Equal;758
18.13.3;Unproxy a Proxy;760
18.13.4;An Entity Object and an Unproxied Object Are Equal;761
18.14;Item 116: How to Map a Database View;762
18.15;Item 117: How to Update a Database View;764
18.15.1;Trigger UPDATE Statements;766
18.15.2;Trigger INSERT Statements;767
18.15.3;Trigger DELETE Statements;768
18.16;Item 118: Why and How to Use WITH CHECK OPTION;770
18.17;Item 119: How to Efficiently Assign a Database Temporary Ranking to Rows;772
18.17.1;Using the ORDER BY Clause in the Query and in the OVER Clause;774
18.17.2;Use Multiple Columns with the OVER Clause;775
18.18;Item 120: How to Efficiently Find Top N Rows of Every Group;776
18.19;Item 121: How to Implement Advanced Search via Specification API;778
18.19.1;Testing Time;782
18.19.1.1;Fetch All Authors Older than 40 of Genre Anthology;782
18.19.1.2;Fetch a Page of Books with a Price Less than 60;783
18.19.2;What’s Next;784
18.20;Item 122: How to Enhance SQL Statement Caching via IN Clause Parameter Padding;784
18.21;Item 123: How to Create Specification Query Fetch Joins;788
18.21.1;Join Fetch and Pagination in Memory;788
18.21.2;Join Fetch and Pagination in Database;790
18.22;Item 124: How to Use a Hibernate-Specific Query Plan Cache;793
18.23;Item 125: How to Check if a Transient Entity Exists in the Database via Spring Query By Example (QBE);795
18.23.1;Head-to-Head Comparison of All Attributes;797
18.23.2;Head-to-Head Comparison of Certain Attributes;798
18.23.3;Apply the or Conjunction to a Subset of Attributes;799
18.24;Item 126: How to Include in the UPDATE Statement Only the Modified Columns via Hibernate @DynamicUpdate;800
18.25;Item 127: How to Use Named (Native) Queries in Spring;802
18.25.1;Referencing a Named (Native) Query;803
18.25.2;Using @NamedQuery and @NamedNativeQuery;803
18.25.3;Using a Properties File ( jpa-named-queries.properties);805
18.26;Item 128: The Best Way to Fetch Parent and Children in Different Queries/Requests;808
18.27;Item 129: How to Optimize the Merge Operation Using Update;812
18.28;Item 130: How to Implement Concurrent Table Based Queues via the SKIP LOCKED Option;815
18.28.1;Set Up SKIP LOCKED;816
18.28.2;Testing Time;817
18.29;Item 131: How to Retry the Transaction After a Versioned (@Version) OptimisticLockException;819
18.29.1;Versioned Optimistic Locking Exception;820
18.29.2;Simulate an Optimistic Locking Exception;822
18.29.3;Retrying the Transaction;823
18.29.4;Testing Scenario;827
18.30;Item 132: How to Retry a Transaction After a Versionless OptimisticLockException;829
18.30.1;Versionless Optimistic Locking Exception;829
18.30.2;Simulate an Optimistic Locking Exception;830
18.30.3;Retrying the Transaction;831
18.30.4;Testing Scenario;831
18.31;Item 133: How to Handle Versioned Optimistic Locking and Detached Entities;832
18.32;Item 134: How to Use the Optimistic Locking Mechanism and Detached Entities in long HTTP Conversations;836
18.32.1;Testing Time;841
18.33;Item 135: How to Increment the Version of the Locked Entity Even If this Entity Was Not Modified;843
18.33.1;OPTIMISTIC_FORCE_INCREMENT;843
18.33.2;PESSIMISTIC_FORCE_INCREMENT;849
18.34;Item 136: How PESSIMISTIC_READ/WRITE Works;854
18.34.1;PESSIMISTIC_READ;856
18.34.1.1;MySQL and MySQL5Dialect Dialects (MyISAM);857
18.34.1.2;MySQL and MySQL5InnoDBDialect/ MySQL8Dialect Dialects (InnoDB);858
18.34.1.3;PostgreSQL and PostgreSQL95Dialect;860
18.34.1.4;Other RDBMS;860
18.34.2;PESSIMISTIC_WRITE;860
18.34.2.1;MySQL and MySQL5Dialect dialect (MyISAM);861
18.34.2.2;MySQL and MySQL5InnoDBDialect/ MySQL8Dialect Dialects (InnoDB);862
18.34.2.3;PostgreSQL and PostgreSQL95Dialect;863
18.34.2.4;Other RDBMS;863
18.35;Item 137: How PESSIMISTIC_WRITE Works with UPDATE/INSERT and DELETE Operations;864
18.35.1;Trigger UPDATE;864
18.35.2;Trigger DELETE;867
18.35.3;Trigger INSERT;870
18.35.3.1;Trigger INSERT in MySQL with REPEATABLE_READ;872
18.35.3.2;Trigger INSERT in MySQL with READ_COMMITTED;873
19;Chapter 15: Inheritance;874
19.1;Item 138: How to Efficiently Use Single Table Inheritance;874
19.1.1;Persisting Data;876
19.1.2;Queries and Single Table Inheritance;877
19.1.2.1;Fetching the Books by Author Identifier;878
19.1.2.2;Fetching the Books by Title;878
19.1.2.3;Fetching the Paperbacks;880
19.1.2.4;Fetching the Author and the Associated Books;881
19.1.3;Subclasses Attributes Non-Nullability Issue;883
19.1.4;Optimize Memory Footprint of the Discriminator Column;886
19.2;Item 139: How to Fetch Certain Subclasses from a SINGLE_TABLE Inheritance Hierarchy;888
19.3;Item 140: How to Efficiently Use Join Table Inheritance;891
19.3.1;Persisting Data;893
19.3.2;Queries and Join Table Inheritance;895
19.3.2.1;Fetching the Books by Author Identifier;895
19.3.2.2;Fetching the Books by Title;896
19.3.2.3;Fetching the Paperbacks;897
19.3.2.4;Fetching the Author and the Associated Books;899
19.3.3;How to Use JPA JOINED Inheritance Strategy and Strategy Design Patterns;903
19.4;Item 141: How to Efficiently Use Table-Per-Class Inheritance;906
19.4.1;Persisting Data;908
19.4.2;Queries and Class-Per-Table Inheritance;909
19.4.2.1;Fetching the Books by Author Identifier;910
19.4.2.2;Fetching the Books by Title;911
19.4.2.3;Fetching the Paperbacks;912
19.4.2.4;Fetching the Author and the Associated Books;913
19.5;Item 142: How to Efficiently Use @MappedSuperclass;917
19.5.1;Persisting Data;919
19.5.1.1;Fetching the Paperbacks;920
20;Chapter 16: Types and Hibernate Types;923
20.1;Item 143: How to Deal with Hibernate and Unsupported Types via the Hibernate Types Library;923
20.2;Item 144: How to Map CLOBs and BLOBs;926
20.2.1;Ease of Use (Trade-Off with Performance);926
20.2.2;Avoiding Performance Penalties (Trade-Off Is Ease of Use);928
20.3;Item 145: How to Efficiently Map a Java Enum to a Database;930
20.3.1;Mapping via EnumType.STRING;931
20.3.2;Mapping via EnumType.ORDINAL;931
20.3.3;Mapping an Enum to a Custom Representation;932
20.3.4;Mapping an Enum to a Database-Specific Enum Type (PostgreSQL);934
20.3.4.1;Writing a Custom Type;934
20.3.4.2;Using the Hibernate Types Library;935
20.4;Item 146: How to Efficiently Map a JSON Java Object to a MySQL JSON Column;936
20.4.1;Persisting an Author;938
20.4.2;Fetching/Updating the Author;938
20.4.3;Fetching the Author by Querying the JSON;939
20.5;Item 147: How to Efficiently Map a JSON Java Object to a PostgreSQL JSON Column;940
20.5.1;Persisting an Author;942
20.5.2;Fetching/Updating the Author;942
20.5.3;Fetching the Author by Querying the JSON;943
21;Appendix A: (Hibernate) JPA Fundamentals;945
21.1;What Is a Persistence Unit?;945
21.2;What Is an EntityManagerFactory?;946
21.3;What Is an EntityManager?;946
21.4;Entity State Transitions;951
22;Appendix B: Associations Efficiency;954
23;Appendix C: Five SQL Performance Tips That Will Save Your Day;955
23.1;Using SQL Functions in the WHERE Clause;955
23.2;The Index Column Order Matters;956
23.3;Primary Key vs. Unique Key;957
23.4;LIKE vs. Equals (=);957
23.5;UNION vs. UNION ALL and JOIN Flavors;959
24;Appendix D: How to Create Useful Database Indexes;961
24.1;JPA 2.1 @Index;961
24.2;Don’t Guess the Indexes;963
24.3;Prioritize the Most Used SQL Queries for Indexing;963
24.4;Important SQL Queries Deserve Indexes;964
24.5;Avoid Sorting Operations by Indexing GROUP BY and ORDER BY;964
24.6;Rely on Indexes for Uniqueness;965
24.7;Rely on Indexes for Foreign Keys;965
24.8;Add Columns for Index-Only Access;966
24.9;Avoid Bad Standards;967
25;Appendix E: SQL Phenomena;968
25.1;Dirty Writes;968
25.2;Dirty Reads;970
25.3;Non-Repeatable Reads;971
25.4;Phantom Reads;972
25.5;Read Skews;973
25.6;Write Skews;974
25.7;Lost Updates;975
26;Appendix F: Spring Transaction Isolation Level;978
26.1;@Transactional(isolation =Isolation.READ_UNCOMMITTED);978
26.2;@Transactional(isolation =Isolation.READ_COMMITTED);980
26.3;@Transactional(isolation =Isolation.REPEATABLE_READ);981
26.4;@Transactional(isolation =Isolation.SERIALIZABLE);982
27;Appendix G: Spring Transaction Propagation;984
27.1;Propagation.REQUIRED;984
27.2;Propagation.REQUIRES_NEW;987
27.3;Propagation.NESTED;990
27.4;Propagation.MANDATORY;992
27.5;Propagation.NEVER;993
27.6;Propagation.NOT_SUPPORTED;995
27.7;Propagation.SUPPORTS;997
28;Appendix H: Understanding the Flushing Mechanism;1001
28.1;Strict Flush Order of Actions;1002
28.2;Flush Before Executing a Data Query Language (DQL): SELECT Query;1003
28.3;Flush Before Transaction Commits;1003
28.4;Automatic Flush Modes;1003
28.5;Let the Code Talk;1007
28.5.1;Global Flush Mode;1009
28.5.2;Session-Level Flush Mode;1012
28.5.3;Query-Level Flush Mode;1013
29;Appendix I: Second Level Cache;1015
29.1;NONSTRICT_READ_WRITE;1016
29.2;READ_ONLY;1017
29.3;READ_WRITE;1017
29.4;TRANSACTIONAL;1018
29.5;Query Cache;1019
30;Appendix J: Tools;1021
31;Appendix K: Hibernate 6;1023
32;Index;1025




