100% found this document useful (1 vote)
121 views

Full Spring Boot Persistence Best Practices: Optimize Java Persistence Performance in Spring Boot Applications 1st Edition Anghel Leonard Ebook All Chapters

Boot

Uploaded by

meekinsavko
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
121 views

Full Spring Boot Persistence Best Practices: Optimize Java Persistence Performance in Spring Boot Applications 1st Edition Anghel Leonard Ebook All Chapters

Boot

Uploaded by

meekinsavko
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 62

Download the full version of the textbook now at textbookfull.

com

Spring Boot Persistence Best Practices:


Optimize Java Persistence Performance in
Spring Boot Applications 1st Edition Anghel
Leonard
https://textbookfull.com/product/spring-boot-
persistence-best-practices-optimize-java-
persistence-performance-in-spring-boot-
applications-1st-edition-anghel-leonard/

Explore and download more textbook at https://textbookfull.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Pro Spring Security: Securing Spring Framework 5 and Boot


2-based Java Applications 2nd Edition Carlo Scarioni

https://textbookfull.com/product/pro-spring-security-securing-spring-
framework-5-and-boot-2-based-java-applications-2nd-edition-carlo-
scarioni/
textbookfull.com

Spring Boot 2 0 Projects Build production grade reactive


applications and microservices with Spring Boot English
Edition Mohamed Shazin Sadakath
https://textbookfull.com/product/spring-boot-2-0-projects-build-
production-grade-reactive-applications-and-microservices-with-spring-
boot-english-edition-mohamed-shazin-sadakath/
textbookfull.com

Practical Microservices Architectural Patterns: Event-


Based Java Microservices with Spring Boot and Spring Cloud
Christudas
https://textbookfull.com/product/practical-microservices-
architectural-patterns-event-based-java-microservices-with-spring-
boot-and-spring-cloud-christudas/
textbookfull.com

The Bioarchaeology of Metabolic Bone Disease 2nd Edition


Megan Brickley

https://textbookfull.com/product/the-bioarchaeology-of-metabolic-bone-
disease-2nd-edition-megan-brickley/

textbookfull.com
An Integrated Solution Based Irregular Driving Detection
1st Edition Rui Sun (Auth.)

https://textbookfull.com/product/an-integrated-solution-based-
irregular-driving-detection-1st-edition-rui-sun-auth/

textbookfull.com

Intelligent City Evaluation System Zhiqiang Wu

https://textbookfull.com/product/intelligent-city-evaluation-system-
zhiqiang-wu/

textbookfull.com

Website Hosting and Migration with Amazon Web Services: A


Practical Guide to Moving Your Website to AWS 1st Edition
Jason Nadon (Auth.)
https://textbookfull.com/product/website-hosting-and-migration-with-
amazon-web-services-a-practical-guide-to-moving-your-website-to-
aws-1st-edition-jason-nadon-auth/
textbookfull.com

Exam Ref 70 761 Querying Data with Transact SQL 1st


Edition Safari

https://textbookfull.com/product/exam-ref-70-761-querying-data-with-
transact-sql-1st-edition-safari/

textbookfull.com

The American Military A Narrative History 1st Edition Brad


D. Lookingbill

https://textbookfull.com/product/the-american-military-a-narrative-
history-1st-edition-brad-d-lookingbill/

textbookfull.com
Responsible Corporate Governance Towards Sustainable and
Effective Governance Structures 1st Edition Maria Aluchna

https://textbookfull.com/product/responsible-corporate-governance-
towards-sustainable-and-effective-governance-structures-1st-edition-
maria-aluchna/
textbookfull.com
Spring Boot
Persistence
Best Practices
Optimize Java Persistence Performance
in Spring Boot Applications

Anghel Leonard

www.allitebooks.com
Spring Boot Persistence
Best Practices
Optimize Java Persistence
Performance in Spring Boot
Applications

Anghel Leonard

www.allitebooks.com
Spring Boot Persistence Best Practices: Optimize Java Persistence Performance in
Spring Boot Applications

Anghel Leonard
Banesti, Romania

ISBN-13 (pbk): 978-1-4842-5625-1 ISBN-13 (electronic): 978-1-4842-5626-8


https://doi.org/10.1007/978-1-4842-5626-8

Copyright © 2020 by Anghel Leonard


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Steve Anglin
Development Editor: Matthew Moodie
Coordinating Editor: Mark Powers
Cover designed by eStudioCalamar
Cover image designed by Freepik (www.freepik.com)
Distributed to the book trade worldwide by Apress Media, LLC, 1 New York Plaza, New York, NY 10004,
U.S.A. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-sbm.com, or visit
www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is Springer
Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation.
For information on translations, please e-mail editorial@apress.com; for reprint, paperback, or audio rights,
please email bookpermissions@springernature.com.
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to
readers on GitHub via the book’s product page, located at www.apress.com/9781484256251. For more
detailed information, please visit http://www.apress.com/source-code.
Printed on acid-free paper

www.allitebooks.com
This book is dedicated to my dear wife, Octavia.

www.allitebooks.com
Table of Contents
About the Author��������������������������������������������������������������������������������������������������xxiii

About the Technical Reviewer�������������������������������������������������������������������������������xxv


Introduction���������������������������������������������������������������������������������������������������������xxvii

Chapter 1: Associations�������������������������������������������������������������������������������������������� 1
Item 1: How to Effectively Shape the @OneToMany Association�������������������������������������������������� 1
Always Cascade from Parent-Side to Child-Side�������������������������������������������������������������������� 2
Don’t Forget to Set mappedBy on the Parent-Side������������������������������������������������������������������ 2
Set orphanRemoval on the Parent-Side���������������������������������������������������������������������������������� 3
Keep Both Sides of the Association in Sync���������������������������������������������������������������������������� 3
Override equals( ) and hashCode( )����������������������������������������������������������������������������������������� 4
Use Lazy Fetching on Both Sides of the Association��������������������������������������������������������������� 5
Pay Attention to How toString( ) Is Overridden������������������������������������������������������������������������ 5
Use @JoinColumn to Specify the Join Column Name������������������������������������������������������������� 5
Author and Book Samples������������������������������������������������������������������������������������������������������� 6
Item 2: Why You Should Avoid the Unidirectional @OneToMany Association�������������������������������� 8
Regular Unidirectional @OneToMany������������������������������������������������������������������������������������ 10
Using @OrderColumn������������������������������������������������������������������������������������������������������������ 15
Using @JoinColumn�������������������������������������������������������������������������������������������������������������� 19
Item 3: How Efficient Is the Unidirectional @ManyToOne����������������������������������������������������������� 22
Adding a New Book to a Certain Author�������������������������������������������������������������������������������� 24
Fetching All Books of an Author��������������������������������������������������������������������������������������������� 26
Paging the Books of an Author���������������������������������������������������������������������������������������������� 27
Fetching All Books of an Author and Adding a New Book������������������������������������������������������ 28
Fetching all Books of an Author and Deleting a Book������������������������������������������������������������ 29

www.allitebooks.com
Table of Contents

Item 4: How to Effectively Shape the @ManyToMany Association���������������������������������������������� 30


Choose the Owner of the Relationship���������������������������������������������������������������������������������� 31
Always Use Set not List��������������������������������������������������������������������������������������������������������� 31
Keep Both Sides of the Association in Sync�������������������������������������������������������������������������� 31
Avoid CascadeType.ALL and CascadeType.REMOVE�������������������������������������������������������������� 31
Setting Up the Join Table������������������������������������������������������������������������������������������������������� 32
Using Lazy Fetching on Both Sides of the Association���������������������������������������������������������� 32
Override equals( ) and hashCode( )��������������������������������������������������������������������������������������� 32
Pay Attention to How toString( ) Is Overridden���������������������������������������������������������������������� 32
Author and Book Samples����������������������������������������������������������������������������������������������������� 32
Item 5: Why Set Is Better than List in @ManyToMany����������������������������������������������������������������� 36
Using List������������������������������������������������������������������������������������������������������������������������������� 36
Using Set������������������������������������������������������������������������������������������������������������������������������� 38
Item 6: Why and When to Avoid Removing Child Entities with CascadeType.Remove and
orphanRemoval=true������������������������������������������������������������������������������������������������������������������ 41
Deleting Authors that Are Already Loaded in the Persistence Context���������������������������������� 45
One Author Has Already Been Loaded in the Persistence Context���������������������������������������� 45
More Authors Have Been Loaded in the Persistence Context������������������������������������������������ 46
One Author and His Associated Books Have Been Loaded in the Persistence Context��������� 48
Deleting When the Author and Books that Should Be Deleted Are Not Loaded in the
Persistence Context��������������������������������������������������������������������������������������������������������������� 50
Item 7: How to Fetch Associations via JPA Entity Graphs����������������������������������������������������������� 52
Defining an Entity Graph via @NamedEntityGraph���������������������������������������������������������������� 53
Ad Hoc Entity Graphs������������������������������������������������������������������������������������������������������������� 59
Defining an Entity Graph via EntityManager�������������������������������������������������������������������������� 61
Item 8: How to Fetch Associations via Entity Sub-­Graphs���������������������������������������������������������� 62
Using @NamedEntityGraph and @NamedSubgraph������������������������������������������������������������� 64
Using the Dot Notation (.) in Ad Hoc Entity Graphs���������������������������������������������������������������� 67
Defining an Entity Sub-Graph via EntityManager������������������������������������������������������������������ 70

vi
Table of Contents

Item 9: How to Handle Entity Graphs and Basic Attributes��������������������������������������������������������� 70


Item 10: How to Filter Associations via a Hibernate-­Specific @Where Annotation��������������������� 75
Item 11: How to Optimize Unidirectional/Bidirectional @OneToOne via @MapsId��������������������� 79
Regular Unidirectional @OneToOne��������������������������������������������������������������������������������������� 79
Regular Bidirectional @OneToOne����������������������������������������������������������������������������������������� 82
@MapsId to the Rescue of @OneToOne�������������������������������������������������������������������������������� 84
Item 12: How to Validate that Only One Association Is Non-Null������������������������������������������������� 87
Testing Time�������������������������������������������������������������������������������������������������������������������������� 89

Chapter 2: Entities�������������������������������������������������������������������������������������������������� 91
Item 13: How to Adopt a Fluent API Style in Entities������������������������������������������������������������������� 91
Fluent-Style via Entity Setters����������������������������������������������������������������������������������������������� 92
Fluent-Style via Additional Methods�������������������������������������������������������������������������������������� 95
Item 14: How to Populate a Child-Side Parent Association via a Hibernate-Specific Proxy�������� 98
Using findById( )�������������������������������������������������������������������������������������������������������������������� 99
Using getOne( )�������������������������������������������������������������������������������������������������������������������� 100
Item 15: How to Use Java 8 Optional in Persistence Layer������������������������������������������������������� 101
Optional in Entities�������������������������������������������������������������������������������������������������������������� 101
Optional in Repositories������������������������������������������������������������������������������������������������������ 103
Item 16: How to Write Immutable Entities��������������������������������������������������������������������������������� 104
Item 17: How to Clone Entities�������������������������������������������������������������������������������������������������� 106
Cloning the Parent and Associating the Books�������������������������������������������������������������������� 107
Cloning the Parent and the Books��������������������������������������������������������������������������������������� 110
Joining These Cases������������������������������������������������������������������������������������������������������������ 113
Item 18: Why and How to Activate Dirty Tracking���������������������������������������������������������������������� 114
Item 19: How to Map a Boolean to a Yes/No����������������������������������������������������������������������������� 117
Item 20: The Best Way to Publish Domain Events from Aggregate Roots��������������������������������� 119
Synchronous Execution������������������������������������������������������������������������������������������������������� 123
Asynchronous Execution����������������������������������������������������������������������������������������������������� 129

vii
Table of Contents

Chapter 3: Fetching���������������������������������������������������������������������������������������������� 135


Item 21: How to Use Direct Fetching����������������������������������������������������������������������������������������� 135
Direct Fetching via Spring Data������������������������������������������������������������������������������������������� 136
Fetching via EntityManager������������������������������������������������������������������������������������������������� 137
Fetching via Hibernate-Specific Session����������������������������������������������������������������������������� 137
Direct Fetching and Session-Level Repeatable-Reads�������������������������������������������������������� 139
Direct Fetching Multiple Entities by ID�������������������������������������������������������������������������������� 146
Item 22: Why Use Read-Only Entities Whenever You Plan to Propagate Changes
to the Database in a Future Persistence Context���������������������������������������������������������������������� 148
Load Author in Read-Write Mode���������������������������������������������������������������������������������������� 148
Load Author in Read-Only Mode������������������������������������������������������������������������������������������ 149
Update the Author���������������������������������������������������������������������������������������������������������������� 150
Item 23: How to Lazy Load the Entity Attributes via Hibernate Bytecode Enhancement���������� 151
Enabling Lazy Loading of Attributes������������������������������������������������������������������������������������ 152
Attribute Lazy Loading and N+1������������������������������������������������������������������������������������������ 155
Attribute Lazy Loading and Lazy Initialization Exceptions��������������������������������������������������� 157
Item 24: How to Lazy Load the Entity Attributes via Subentities����������������������������������������������� 163
Item 25: How to Fetch DTO via Spring Projections�������������������������������������������������������������������� 167
JPA Named (Native) Queries Can Be Combined with Spring Projections���������������������������� 172
Class-Based Projections������������������������������������������������������������������������������������������������������ 176
How to Reuse a Spring Projection��������������������������������������������������������������������������������������� 177
How to Use Dynamic Spring Projections����������������������������������������������������������������������������� 179
Item 26: How to Add an Entity in a Spring Projection���������������������������������������������������������������� 181
Materialized Association������������������������������������������������������������������������������������������������������ 181
Not Materialized Association����������������������������������������������������������������������������������������������� 182
Item 27: How to Enrich Spring Projections with Virtual Properties
That Are/Aren’t Part of Entities������������������������������������������������������������������������������������������������� 184
Item 28: How to Efficiently Fetch Spring Projection Including *-to-One Associations�������������� 186
Using Nested Closed Projections����������������������������������������������������������������������������������������� 187
Using a Simple Closed Projection���������������������������������������������������������������������������������������� 190
Using a Simple Open Projection������������������������������������������������������������������������������������������ 192
viii
Table of Contents

Item 29: Why to Pay Attention to Spring Projections that Include Associated Collections�������� 195
Using Nested Spring Closed Projection������������������������������������������������������������������������������� 195
Using a Simple Closed Projection���������������������������������������������������������������������������������������� 206
Transform List<Object[ ]> in DTO���������������������������������������������������������������������������������������� 208
Item 30: How to Fetch All Entity Attributes via Spring Projection���������������������������������������������� 213
Using the Query Builder Mechanism����������������������������������������������������������������������������������� 215
Using JPQL and @Query������������������������������������������������������������������������������������������������������ 215
Using JPQL with an Explicit List of Columns and @Query��������������������������������������������������� 217
Using a Native Query and @Query�������������������������������������������������������������������������������������� 218
Item 31: How to Fetch DTO via Constructor Expression������������������������������������������������������������ 219
Item 32: Why You Should Avoid Fetching Entities in DTO via the Constructor Expression�������� 223
Item 33: How to Fetch DTO via a JPA Tuple������������������������������������������������������������������������������� 226
Item 34: How to Fetch DTO via @SqlResultSetMapping and @NamedNativeQuery����������������� 229
Scalar Mappings������������������������������������������������������������������������������������������������������������������ 230
Constructor Mapping����������������������������������������������������������������������������������������������������������� 231
Entity Mapping��������������������������������������������������������������������������������������������������������������������� 233
Item 35: How to Fetch DTO via ResultTransformer������������������������������������������������������������������� 233
Item 36: How to Fetch DTO via a custom ResultTransformer���������������������������������������������������� 238
Item 37: How to Map an Entity to a Query via @Subselect������������������������������������������������������� 243
Item 38: How to Fetch DTO via Blaze-Persistence Entity Views������������������������������������������������ 247
Item 39: How to Effectively Fetch Parent and Association in One SELECT�������������������������������� 251
Item 40: How to Decide Between JOIN and JOIN FETCH����������������������������������������������������������� 256
Fetch All Authors and Their Books that Are More Expensive than the Given Price�������������� 257
How JOIN FETCH Will Act����������������������������������������������������������������������������������������������������� 258
How JOIN Will Act���������������������������������������������������������������������������������������������������������������� 259
Fetch All Books and their Authors��������������������������������������������������������������������������������������� 261
How JOIN FETCH Will Act����������������������������������������������������������������������������������������������������� 262
How JOIN Will Act���������������������������������������������������������������������������������������������������������������� 263
Item 41: How to Fetch All Left Entities�������������������������������������������������������������������������������������� 265
Item 42: How to Fetch DTO from Unrelated Entities������������������������������������������������������������������ 267

ix
Table of Contents

Item 43: How to Write JOIN Statements������������������������������������������������������������������������������������ 268


INNER JOIN�������������������������������������������������������������������������������������������������������������������������� 270
LEFT JOIN���������������������������������������������������������������������������������������������������������������������������� 271
RIGHT JOIN�������������������������������������������������������������������������������������������������������������������������� 272
CROSS JOIN������������������������������������������������������������������������������������������������������������������������� 273
FULL JOIN���������������������������������������������������������������������������������������������������������������������������� 275
Simulate a FULL JOIN in MySQL������������������������������������������������������������������������������������������ 276
Item 44: How to Paginate JOINs������������������������������������������������������������������������������������������������ 277
The DENSE_RANK( ) Window Function to the Rescue��������������������������������������������������������� 283
Item 45: How to Stream the Result Set (in MySQL) and How to Use the Streamable Utility����� 287
Stream the Result Set (in MySQL)��������������������������������������������������������������������������������������� 287
Do Not Confuse Stream with the Streamable Utility������������������������������������������������������������ 288
Don’t Fetch More Columns than Needed Just to Drop a Part of them via map( )���������������� 290
Don’t Fetch More Rows than Needed Just to Drop a Part of Them via filter( )�������������������� 290
Pay Attention to Concatenating Streamable via and( )�������������������������������������������������������� 291
How to Return Custom Streamable Wrapper Types������������������������������������������������������������� 293

Chapter 4: Batching���������������������������������������������������������������������������������������������� 297


Item 46: How to Batch Inserts in Spring Boot Style������������������������������������������������������������������ 297
Enabling Batching and Preparing the JDBC URL����������������������������������������������������������������� 297
Preparing the Entities for Batching Inserts�������������������������������������������������������������������������� 300
Identify and Avoid the Built-In saveAll(Iterable<S> entities) Drawbacks���������������������������� 302
Custom Implementation Is the Way to Go���������������������������������������������������������������������������� 303
Testing Time������������������������������������������������������������������������������������������������������������������������ 307
Item 47: How to Optimize Batch Inserts of Parent-­Child Relationships������������������������������������ 309
Ordering Inserts������������������������������������������������������������������������������������������������������������������� 310
Item 48: How to Control Batch Size at the Session Level��������������������������������������������������������� 312
Item 49: How to Fork-Join JDBC Batching�������������������������������������������������������������������������������� 313
Fork-Join Batching�������������������������������������������������������������������������������������������������������������� 314
Item 50: Batching Entities via CompletableFuture�������������������������������������������������������������������� 318

x
Visit https://textbookfull.com
now to explore a rich
collection of eBooks, textbook
and enjoy exciting offers!
Table of Contents

Item 51: How to Efficiently Batch Updates�������������������������������������������������������������������������������� 322


Versioned Entities���������������������������������������������������������������������������������������������������������������� 323
Batch Updates of Parent-Child Relationships���������������������������������������������������������������������� 323
Bulk Updates����������������������������������������������������������������������������������������������������������������������� 324
Item 52: How to Efficiently Batch Deletes (No Associations)���������������������������������������������������� 326
Delete via the Built-In deleteAllInBatch( ) Method��������������������������������������������������������������� 328
Delete via the Built-In deleteInBatch(Iterable<T> entities) ������������������������������������������������ 329
Delete via the Built-In deleteAll( ) Methods������������������������������������������������������������������������� 331
Delete via the Built-In delete(T entity) Method�������������������������������������������������������������������� 333
Item 53: How to Efficiently Batch Deletes (with Associations)�������������������������������������������������� 334
Relying on orphanRemoval = true��������������������������������������������������������������������������������������� 335
Delete via the Built-In deleteInBatch(Iterable<T> entities) ������������������������������������������������ 337
Delete via the Built-In deleteAll(Iterable<? extends T> entities) and
delete(T entity) Methods������������������������������������������������������������������������������������������������������ 338
Relying on SQL, ON DELETE CASCADE��������������������������������������������������������������������������������� 342
Delete via the Built-In deleteAllInBatch( ) Method��������������������������������������������������������������� 343
Delete via the Built-In deleteInBatch(Iterable<T> entities) ������������������������������������������������ 343
Delete via the Built-In deleteAll(Iterable<? extends T> entities) and
delete(T entity) Methods������������������������������������������������������������������������������������������������������ 344
Item 54: How to Fetch Association in Batches�������������������������������������������������������������������������� 346
@BatchSize at the Collection-Level������������������������������������������������������������������������������������ 346
@BatchSize at Class/Entity-Level��������������������������������������������������������������������������������������� 349
Item 55: Why to Avoid PostgreSQL (BIG)SERIAL in Batching Inserts via Hibernate������������������� 352
Optimize the Identifier-Fetching Process���������������������������������������������������������������������������� 353
Optimize Batching via reWriteBatchedInserts��������������������������������������������������������������������� 354

Chapter 5: Collections������������������������������������������������������������������������������������������ 357


Item 56: How to JOIN FETCH an @ElementCollection Collection���������������������������������������������� 357
Item 57: How to DTO an @ElementCollection��������������������������������������������������������������������������� 359
Item 58: Why and When to Use @OrderColumn with @ElementCollection������������������������������� 362
Optimizing @ElementCollection via @OrderColumn����������������������������������������������������������� 366

xi
Table of Contents

Item 59: How to Merge Entity Collections��������������������������������������������������������������������������������� 373


Merging the Detached Collection���������������������������������������������������������������������������������������� 377
Testing Time������������������������������������������������������������������������������������������������������������������������ 380

Chapter 6: Connections and Transactions������������������������������������������������������������ 383


Item 60: How to Delay Connection Acquisition Until It’s Really Needed������������������������������������ 383
Item 61: How @Transactional(readOnly=true) Really Works����������������������������������������������������� 386
Item 62: Why Spring Ignores @Transactional��������������������������������������������������������������������������� 396
Item 63: How to Set and Check that Transaction Timeout and Rollback at Expiration Work as
Expected����������������������������������������������������������������������������������������������������������������������������������� 400
Setting Transaction and Query Timeouts����������������������������������������������������������������������������� 403
Check That a Transaction Was Rolled Back������������������������������������������������������������������������� 404
Item 64: Why and How to Use @Transactional in a Repository Interface���������������������������������� 404
Does Query-methods listed in an interface repository run by default
in a transactional-context?�������������������������������������������������������������������������������������������������� 405
Okay, So All I Have to Do Is Add @Transactional at the Service-Method Level, Right?������� 410
But, Generally Speaking, Is this Approach Always Enough?������������������������������������������������ 414
I Know! Let’s Move @Transactional in the Repository Interface!���������������������������������������� 416
But What If I Want to Call More Query-Methods in the Service-­Method?
Do I Lose ACID?������������������������������������������������������������������������������������������������������������������� 417
So, If I Delay the Connection Acquisition then I Can Avoid @Transactional in
Repository Interfaces?�������������������������������������������������������������������������������������������������������� 422
Three Simple and Common Scenarios�������������������������������������������������������������������������������� 426

Chapter 7: Identifiers�������������������������������������������������������������������������������������������� 433


Item 65: Why to Avoid the Hibernate 5 AUTO Generator Type in MySQL������������������������������������ 433
Item 66: How to Optimize the Generation of Sequence Identifiers via the
hi/lo Algorithm��������������������������������������������������������������������������������������������������������������������������� 435
Dealing with External Systems�������������������������������������������������������������������������������������������� 440
Item 67: How to Optimize the Generation of Sequence Identifiers via Pooled (-lo)
Algorithms��������������������������������������������������������������������������������������������������������������������������������� 441
The Pooled Algorithm���������������������������������������������������������������������������������������������������������� 442
The Pooled-Lo Algorithm����������������������������������������������������������������������������������������������������� 445

xii
Table of Contents

Item 68: How to Correctly Override equals( ) and hashCode( )������������������������������������������������� 448
Building the Unit Test����������������������������������������������������������������������������������������������������������� 448
Best Approaches for Overriding equals( ) and hashCode( )������������������������������������������������� 451
Approaches for Overriding equals( ) and hashCode( ) that Must Be Avoided���������������������� 458
Item 69: How to Use Hibernate-Specific @NaturalId in Spring Style���������������������������������������� 463
Testing Time������������������������������������������������������������������������������������������������������������������������ 467
Compound Natural ID���������������������������������������������������������������������������������������������������������� 468
Item 70: How to Use Hibernate-Specific @NaturalId and Skip the Entity
Identifier Retrieval��������������������������������������������������������������������������������������������������������������������� 471
Using @NaturalIdCache Solely�������������������������������������������������������������������������������������������� 472
Using @NaturalIdCache and @Cache���������������������������������������������������������������������������������� 474
Item 71: How to Define an Association that References a @NaturalId Column������������������������ 477
Testing Time������������������������������������������������������������������������������������������������������������������������ 478
Item 72: How to Obtain Auto-Generated Keys��������������������������������������������������������������������������� 479
Retrieve Auto-Generated Keys via getId( )��������������������������������������������������������������������������� 480
Retrieve Auto-Generated Keys via JdbcTemplate���������������������������������������������������������������� 480
Retrieve Auto-Generated Keys via SimpleJdbcInsert���������������������������������������������������������� 482
Item 73: How to Generate Custom Sequence IDs��������������������������������������������������������������������� 482
Item 74: How to Efficiently Implement a Composite Primary Key��������������������������������������������� 484
Composite key via @Embeddable and @EmbeddedId�������������������������������������������������������� 486
Composite key via @IdClass����������������������������������������������������������������������������������������������� 497
How About the Universally Unique Identifier (UUID)?���������������������������������������������������������� 498
Generate UUID via GenerationType.AUTO����������������������������������������������������������������������������� 499
Manually Assigned UUID������������������������������������������������������������������������������������������������������ 501
Hibernate-Specific uuid2����������������������������������������������������������������������������������������������������� 502
Item 75: How to Define a Relationship in a Composite Key������������������������������������������������������ 503
Testing Time������������������������������������������������������������������������������������������������������������������������ 508
Persist a Publisher��������������������������������������������������������������������������������������������������������������� 508
Persist Two Authors������������������������������������������������������������������������������������������������������������� 509
Find an Author by Name������������������������������������������������������������������������������������������������������ 512

xiii
Table of Contents

Remove a Book of an Author����������������������������������������������������������������������������������������������� 513


Remove an Author��������������������������������������������������������������������������������������������������������������� 514
Item 76: How to Use an Entity for the Junction Table��������������������������������������������������������������� 516
Define a Composite Primary Key for the Junction Table����������������������������������������������������� 516
Define an Entity for the Junction Table�������������������������������������������������������������������������������� 518
Plug In the Author and Book������������������������������������������������������������������������������������������������ 520

Chapter 8: Calculating Properties������������������������������������������������������������������������� 523


Item 77: How to Map Calculated Non-Persistent Properties����������������������������������������������������� 523
JPA Quick Approach������������������������������������������������������������������������������������������������������������ 523
JPA @PostLoad������������������������������������������������������������������������������������������������������������������� 524
Hibernate-specific @Formula��������������������������������������������������������������������������������������������� 525
Item 78: How to Map Calculated Persistent Properties via @Generated���������������������������������� 526
Hibernate-Specific @Generated������������������������������������������������������������������������������������������ 527
Item 79: How to Use SQL Functions with Multiple Parameters in JPQL Queries���������������������� 531
Function in the SELECT Part������������������������������������������������������������������������������������������������ 532
Function in the WHERE Part������������������������������������������������������������������������������������������������� 534
Item 80: How to Map @ManyToOne Relationship to an SQL Query Via @JoinFormula������������� 536

Chapter 9: Monitoring������������������������������������������������������������������������������������������� 541


Item 81: Why and How to Count and Assert SQL Statements��������������������������������������������������� 541
Item 82: How to Log the Binding and Extracted Parameters of a Prepared Statement������������ 546
TRACE���������������������������������������������������������������������������������������������������������������������������������� 546
Log4j 2��������������������������������������������������������������������������������������������������������������������������������� 548
MySQL and profileSQL=true������������������������������������������������������������������������������������������������ 549
Item 83: How to Log Query Details�������������������������������������������������������������������������������������������� 549
Via DataSource-Proxy���������������������������������������������������������������������������������������������������������� 549
Via log4jdbc������������������������������������������������������������������������������������������������������������������������� 550
Via P6spy����������������������������������������������������������������������������������������������������������������������������� 551
Item 84: How to Log Slow Queries with Threshold������������������������������������������������������������������� 552
Item 85: Log Transactions and Query-Methods Details������������������������������������������������������������� 554
Log Transactions Details������������������������������������������������������������������������������������������������������ 554
xiv
Table of Contents

Take Control via Transaction Callbacks������������������������������������������������������������������������������� 554


Log Query-Methods Execution Time������������������������������������������������������������������������������������ 557

Chapter 10: Configuring DataSource and Connection Pool����������������������������������� 561


Item 86: How to Customize HikariCP Settings�������������������������������������������������������������������������� 561
Tuning HikariCP Parameters via application.properties������������������������������������������������������ 562
Tuning HikariCP Parameters via application.properties and DataSourceBuilder����������������� 563
Tuning HikariCP Parameters via DataSourceBuilder����������������������������������������������������������� 564
Tuning Other Connection Pools�������������������������������������������������������������������������������������������� 565
Item 87: How to Configure Two Data Sources with Two Connection Pools������������������������������� 566
Testing Time������������������������������������������������������������������������������������������������������������������������ 572

Chapter 11: Audit�������������������������������������������������������������������������������������������������� 575


Item 88: How to Track the Creation and Modification Times and Entity Users�������������������������� 575
Rely on Spring Data JPA Auditing���������������������������������������������������������������������������������������� 576
Relying on Hibernate Support���������������������������������������������������������������������������������������������� 579
The createdBy and lastModifiedBy Fields��������������������������������������������������������������������������� 580
Testing Time������������������������������������������������������������������������������������������������������������������������ 583
Item 89: How to Enable Hibernate-Specific Envers Auditing���������������������������������������������������� 584
Auditing Entities������������������������������������������������������������������������������������������������������������������ 585
Schema Generation������������������������������������������������������������������������������������������������������������� 586
Querying the Entity Snapshots�������������������������������������������������������������������������������������������� 588
Item 90: How to Inspect the Persistence Context��������������������������������������������������������������������� 591
Item 91: How to Extract Table Metadata����������������������������������������������������������������������������������� 596

Chapter 12: Schemas�������������������������������������������������������������������������������������������� 601


Item 92: How to Set Up Flyway in Spring Boot�������������������������������������������������������������������������� 601
Quickest Flyway Setup (MySQL and PostgreSQL)��������������������������������������������������������������� 601
Instruct Flyway to Create the Database������������������������������������������������������������������������������� 602
Set Up Flyway via @FlywayDataSource������������������������������������������������������������������������������ 605
Flyway and Multiple Schemas��������������������������������������������������������������������������������������������� 606
Item 93: How to Generate Two Databases via schema-*.sql and Match Entities to Them�������� 606

xv
Table of Contents

Chapter 13: Pagination����������������������������������������������������������������������������������������� 609


Item 94: When and Why Offset Pagination May Become a Performance Penalty��������������������� 609
Index Scan in Offset and Keyset������������������������������������������������������������������������������������������ 609
Offset Pagination Pros and Cons����������������������������������������������������������������������������������������� 610
Spring Boot Offset Pagination��������������������������������������������������������������������������������������������� 612
Item 95: How to Optimize Offset Pagination with COUNT(*) OVER and Page<entity/dto>�������� 619
COUNT(*) OVER( ) Windowed Aggregate������������������������������������������������������������������������������ 619
Item 96: How to Optimize Offset Pagination with SELECT COUNT subquery and
Page<entity/dto>���������������������������������������������������������������������������������������������������������������������� 628
SELECT COUNT Subquery���������������������������������������������������������������������������������������������������� 628
Item 97: How to Use JOIN FETCH and Pageable����������������������������������������������������������������������� 636
Item 98: How to Fix HHH000104����������������������������������������������������������������������������������������������� 640
Fetching Managed Entities�������������������������������������������������������������������������������������������������� 641
Item 99: How to Implement Slice<T> findAll( )������������������������������������������������������������������������� 651
Quick Implementation��������������������������������������������������������������������������������������������������������� 652
Implementation of Slice<T> findAll(Pageable pageable)���������������������������������������������������� 656
Item 100: How to Implement Keyset Pagination����������������������������������������������������������������������� 658
Item 101: How to Add a Next Page Button to Keyset Pagination���������������������������������������������� 662
Item 102: How to Implement Pagination via ROW_NUMBER( )������������������������������������������������� 665

Chapter 14: Queries���������������������������������������������������������������������������������������������� 667


Item 103: How to Optimize SELECT DISTINCT via Hibernate-Specific
HINT_PASS_DISTINCT_THROUGH��������������������������������������������������������������������������������������������� 667
Item 104: How to Set Up JPA Callbacks������������������������������������������������������������������������������������ 673
Separate Listener Class via @EntityListeners��������������������������������������������������������������������� 675
Item 105: How to Use Spring Data Query Builder to limit the Result Set Size and to
Count and Delete Derived Queries�������������������������������������������������������������������������������������������� 677
Limiting the Result Set Size������������������������������������������������������������������������������������������������ 677
Count and Delete Derived Queries��������������������������������������������������������������������������������������� 682
Item 106: Why You Should Avoid Time-Consuming Tasks in Post-Commits������������������������������ 683
Item 107: How to Avoid Redundant save( ) Calls����������������������������������������������������������������������� 685

xvi
Table of Contents

Item 108: Why and How to Prevent N+1 Issues������������������������������������������������������������������������ 687


Hibernate-Specific @Fetch(FetchMode.JOIN) and N+1������������������������������������������������������ 689
Item 109: How to Use Hibernate-Specific Soft Deletes Support����������������������������������������������� 694
Hibernate Soft Deletes�������������������������������������������������������������������������������������������������������� 696
Item 110: Why and How to Avoid the OSIV Anti-Pattern������������������������������������������������������������ 704
Hibernate5Module��������������������������������������������������������������������������������������������������������������� 708
Explicitly (Manually) Initializing the Unfetched Lazy Properties������������������������������������������ 711
How About the Hibernate-Specific hibernate.enable_lazy_load_no_trans������������������������� 713
Item 111: How to Store Date/Time in UTC Time Zone (MySQL)������������������������������������������������� 714
Item 112: How to Shuffle Small Result Sets via ORDER BY RAND( )����������������������������������������� 717
Item 113: How to Use Subqueries in the WHERE/HAVING Clause��������������������������������������������� 718
Item 114: How to Call a Stored Procedure�������������������������������������������������������������������������������� 722
Calling a Stored Procedure that Returns a Value (Scalar Data Types)��������������������������������� 723
Calling a Stored Procedure that Returns a Result Set��������������������������������������������������������� 725
Item 115: How to Unproxy a Proxy�������������������������������������������������������������������������������������������� 736
What Is a Proxy Object?������������������������������������������������������������������������������������������������������� 736
An Entity Object and a Proxy Object Are Not Equal�������������������������������������������������������������� 737
Unproxy a Proxy������������������������������������������������������������������������������������������������������������������� 739
An Entity Object and an Unproxied Object Are Equal����������������������������������������������������������� 740
Item 116: How to Map a Database View����������������������������������������������������������������������������������� 741
Item 117: How to Update a Database View������������������������������������������������������������������������������� 743
Trigger UPDATE Statements������������������������������������������������������������������������������������������������� 745
Trigger INSERT Statements������������������������������������������������������������������������������������������������� 746
Trigger DELETE Statements������������������������������������������������������������������������������������������������� 747
Item 118: Why and How to Use WITH CHECK OPTION��������������������������������������������������������������� 749
Item 119: How to Efficiently Assign a Database Temporary Ranking to Rows�������������������������� 751
Using the ORDER BY Clause in the Query and in the OVER Clause�������������������������������������� 753
Use Multiple Columns with the OVER Clause���������������������������������������������������������������������� 754
Item 120: How to Efficiently Find Top N Rows of Every Group�������������������������������������������������� 755

xvii
Table of Contents

Item 121: How to Implement Advanced Search via Specification API��������������������������������������� 757
Testing Time������������������������������������������������������������������������������������������������������������������������ 761
What’s Next������������������������������������������������������������������������������������������������������������������������� 763
Item 122: How to Enhance SQL Statement Caching via IN Clause Parameter Padding������������ 763
Item 123: How to Create Specification Query Fetch Joins�������������������������������������������������������� 767
Join Fetch and Pagination in Memory��������������������������������������������������������������������������������� 767
Join Fetch and Pagination in Database������������������������������������������������������������������������������� 769
Item 124: How to Use a Hibernate-Specific Query Plan Cache������������������������������������������������� 772
Item 125: How to Check if a Transient Entity Exists in the Database via Spring Query
By Example (QBE)���������������������������������������������������������������������������������������������������������������������� 774
Head-to-Head Comparison of All Attributes������������������������������������������������������������������������� 776
Head-to-Head Comparison of Certain Attributes����������������������������������������������������������������� 777
Apply the or Conjunction to a Subset of Attributes�������������������������������������������������������������� 778
Item 126: How to Include in the UPDATE Statement Only the Modified Columns via
Hibernate @DynamicUpdate����������������������������������������������������������������������������������������������������� 779
Item 127: How to Use Named (Native) Queries in Spring���������������������������������������������������������� 781
Referencing a Named (Native) Query���������������������������������������������������������������������������������� 782
Using @NamedQuery and @NamedNativeQuery���������������������������������������������������������������� 782
Using a Properties File ( jpa-named-queries.properties)����������������������������������������������������� 784
Item 128: The Best Way to Fetch Parent and Children in Different Queries/Requests�������������� 787
Item 129: How to Optimize the Merge Operation Using Update������������������������������������������������ 791
Item 130: How to Implement Concurrent Table Based Queues via the SKIP LOCKED Option���� 794
Set Up SKIP LOCKED������������������������������������������������������������������������������������������������������������ 795
Testing Time������������������������������������������������������������������������������������������������������������������������ 796
Item 131: How to Retry the Transaction After a Versioned (@Version)
OptimisticLockException����������������������������������������������������������������������������������������������������������� 798
Versioned Optimistic Locking Exception������������������������������������������������������������������������������ 799
Simulate an Optimistic Locking Exception�������������������������������������������������������������������������� 801
Retrying the Transaction������������������������������������������������������������������������������������������������������ 802
Testing Scenario������������������������������������������������������������������������������������������������������������������ 806

xviii
Table of Contents

Item 132: How to Retry a Transaction After a Versionless OptimisticLockException���������������� 808


Versionless Optimistic Locking Exception��������������������������������������������������������������������������� 808
Simulate an Optimistic Locking Exception�������������������������������������������������������������������������� 809
Retrying the Transaction������������������������������������������������������������������������������������������������������ 810
Testing Scenario������������������������������������������������������������������������������������������������������������������ 810
Item 133: How to Handle Versioned Optimistic Locking and Detached Entities������������������������ 811
Item 134: How to Use the Optimistic Locking Mechanism and Detached
Entities in long HTTP Conversations����������������������������������������������������������������������������������������� 815
Testing Time������������������������������������������������������������������������������������������������������������������������ 820
Item 135: How to Increment the Version of the Locked Entity Even If this
Entity Was Not Modified������������������������������������������������������������������������������������������������������������ 822
OPTIMISTIC_FORCE_INCREMENT���������������������������������������������������������������������������������������� 822
PESSIMISTIC_FORCE_INCREMENT�������������������������������������������������������������������������������������� 828
Item 136: How PESSIMISTIC_READ/WRITE Works�������������������������������������������������������������������� 833
PESSIMISTIC_READ������������������������������������������������������������������������������������������������������������� 835
PESSIMISTIC_WRITE������������������������������������������������������������������������������������������������������������ 839
Item 137: How PESSIMISTIC_WRITE Works with UPDATE/INSERT and DELETE Operations������ 843
Trigger UPDATE�������������������������������������������������������������������������������������������������������������������� 843
Trigger DELETE�������������������������������������������������������������������������������������������������������������������� 846
Trigger INSERT��������������������������������������������������������������������������������������������������������������������� 849

Chapter 15: Inheritance���������������������������������������������������������������������������������������� 853


Item 138: How to Efficiently Use Single Table Inheritance�������������������������������������������������������� 853
Persisting Data�������������������������������������������������������������������������������������������������������������������� 855
Queries and Single Table Inheritance���������������������������������������������������������������������������������� 856
Subclasses Attributes Non-Nullability Issue������������������������������������������������������������������������ 862
Optimize Memory Footprint of the Discriminator Column��������������������������������������������������� 865
Item 139: How to Fetch Certain Subclasses from a SINGLE_TABLE Inheritance Hierarchy������ 867
Item 140: How to Efficiently Use Join Table Inheritance����������������������������������������������������������� 870
Persisting Data�������������������������������������������������������������������������������������������������������������������� 872
Queries and Join Table Inheritance������������������������������������������������������������������������������������� 874
How to Use JPA JOINED Inheritance Strategy and Strategy Design Patterns��������������������� 882
xix
Table of Contents

Item 141: How to Efficiently Use Table-Per-Class Inheritance�������������������������������������������������� 885


Persisting Data�������������������������������������������������������������������������������������������������������������������� 887
Queries and Class-Per-Table Inheritance���������������������������������������������������������������������������� 888
Item 142: How to Efficiently Use @MappedSuperclass������������������������������������������������������������ 896
Persisting Data�������������������������������������������������������������������������������������������������������������������� 898

Chapter 16: Types and Hibernate Types���������������������������������������������������������������� 903


Item 143: How to Deal with Hibernate and Unsupported Types via the Hibernate
Types Library����������������������������������������������������������������������������������������������������������������������������� 903
Item 144: How to Map CLOBs and BLOBs��������������������������������������������������������������������������������� 906
Ease of Use (Trade-Off with Performance)�������������������������������������������������������������������������� 906
Avoiding Performance Penalties (Trade-Off Is Ease of Use)������������������������������������������������ 908
Item 145: How to Efficiently Map a Java Enum to a Database�������������������������������������������������� 910
Mapping via EnumType.STRING������������������������������������������������������������������������������������������� 911
Mapping via EnumType.ORDINAL���������������������������������������������������������������������������������������� 911
Mapping an Enum to a Custom Representation������������������������������������������������������������������ 912
Mapping an Enum to a Database-Specific Enum Type (PostgreSQL)���������������������������������� 914
Item 146: How to Efficiently Map a JSON Java Object to a MySQL JSON Column�������������������� 916
Persisting an Author������������������������������������������������������������������������������������������������������������ 918
Fetching/Updating the Author���������������������������������������������������������������������������������������������� 918
Fetching the Author by Querying the JSON������������������������������������������������������������������������� 919
Item 147: How to Efficiently Map a JSON Java Object to a PostgreSQL JSON Column������������ 920
Persisting an Author������������������������������������������������������������������������������������������������������������ 922
Fetching/Updating the Author���������������������������������������������������������������������������������������������� 922
Fetching the Author by Querying the JSON������������������������������������������������������������������������� 923

Appendix A: (Hibernate) JPA Fundamentals��������������������������������������������������������� 925


What Is a Persistence Unit?������������������������������������������������������������������������������������������������������ 925
What Is an EntityManagerFactory?������������������������������������������������������������������������������������������� 926
What Is an EntityManager?������������������������������������������������������������������������������������������������������� 926
Entity State Transitions������������������������������������������������������������������������������������������������������������� 931

Appendix B: Associations Efficiency�������������������������������������������������������������������� 935


xx
Visit https://textbookfull.com
now to explore a rich
collection of eBooks, textbook
and enjoy exciting offers!
Table of Contents

Appendix C: Five SQL Performance Tips That Will Save Your Day������������������������ 937
Using SQL Functions in the WHERE Clause������������������������������������������������������������������������������� 937
The Index Column Order Matters���������������������������������������������������������������������������������������������� 938
Primary Key vs. Unique Key������������������������������������������������������������������������������������������������������ 939
LIKE vs. Equals (=)�������������������������������������������������������������������������������������������������������������������� 939
UNION vs. UNION ALL and JOIN Flavors������������������������������������������������������������������������������������ 941

Appendix D: How to Create Useful Database Indexes������������������������������������������� 943


JPA 2.1 @Index������������������������������������������������������������������������������������������������������������������������� 943
Don’t Guess the Indexes����������������������������������������������������������������������������������������������������������� 945
Prioritize the Most Used SQL Queries for Indexing������������������������������������������������������������������� 945
Important SQL Queries Deserve Indexes����������������������������������������������������������������������������������� 946
Avoid Sorting Operations by Indexing GROUP BY and ORDER BY���������������������������������������������� 946
Rely on Indexes for Uniqueness������������������������������������������������������������������������������������������������ 947
Rely on Indexes for Foreign Keys���������������������������������������������������������������������������������������������� 947
Add Columns for Index-Only Access����������������������������������������������������������������������������������������� 948
Avoid Bad Standards����������������������������������������������������������������������������������������������������������������� 949

Appendix E: SQL Phenomena�������������������������������������������������������������������������������� 951


Dirty Writes������������������������������������������������������������������������������������������������������������������������������� 951
Dirty Reads�������������������������������������������������������������������������������������������������������������������������������� 953
Non-Repeatable Reads������������������������������������������������������������������������������������������������������������� 954
Phantom Reads������������������������������������������������������������������������������������������������������������������������� 955
Read Skews������������������������������������������������������������������������������������������������������������������������������ 956
Write Skews������������������������������������������������������������������������������������������������������������������������������ 957
Lost Updates����������������������������������������������������������������������������������������������������������������������������� 958

Appendix F: Spring Transaction Isolation Level���������������������������������������������������� 961


@Transactional(isolation =Isolation.READ_UNCOMMITTED)����������������������������������������������������� 961
@Transactional(isolation =Isolation.READ_COMMITTED)��������������������������������������������������������� 963
@Transactional(isolation =Isolation.REPEATABLE_READ)��������������������������������������������������������� 964
@Transactional(isolation =Isolation.SERIALIZABLE)����������������������������������������������������������������� 965

xxi
Table of Contents

Appendix G: Spring Transaction Propagation������������������������������������������������������� 967


Propagation.REQUIRED������������������������������������������������������������������������������������������������������������� 967
Propagation.REQUIRES_NEW���������������������������������������������������������������������������������������������������� 970
Propagation.NESTED����������������������������������������������������������������������������������������������������������������� 973
Propagation.MANDATORY���������������������������������������������������������������������������������������������������������� 975
Propagation.NEVER������������������������������������������������������������������������������������������������������������������� 976
Propagation.NOT_SUPPORTED�������������������������������������������������������������������������������������������������� 978
Propagation.SUPPORTS������������������������������������������������������������������������������������������������������������� 980

Appendix H: Understanding the Flushing Mechanism������������������������������������������ 985


Strict Flush Order of Actions����������������������������������������������������������������������������������������������������� 986
Flush Before Executing a Data Query Language (DQL): SELECT Query������������������������������������� 987
Flush Before Transaction Commits������������������������������������������������������������������������������������������� 987
Automatic Flush Modes������������������������������������������������������������������������������������������������������������ 987
Let the Code Talk����������������������������������������������������������������������������������������������������������������������� 991
Global Flush Mode�������������������������������������������������������������������������������������������������������������������� 993
Session-Level Flush Mode�������������������������������������������������������������������������������������������������������� 996
Query-Level Flush Mode����������������������������������������������������������������������������������������������������������� 997

Appendix I: Second Level Cache��������������������������������������������������������������������������� 999


NONSTRICT_READ_WRITE������������������������������������������������������������������������������������������������������ 1000
READ_ONLY����������������������������������������������������������������������������������������������������������������������������� 1001
READ_WRITE��������������������������������������������������������������������������������������������������������������������������� 1001
TRANSACTIONAL��������������������������������������������������������������������������������������������������������������������� 1002
Query Cache���������������������������������������������������������������������������������������������������������������������������� 1003

Appendix J: Tools����������������������������������������������������������������������������������������������� 1005

Appendix K: Hibernate 6������������������������������������������������������������������������������������� 1007

Index������������������������������������������������������������������������������������������������������������������� 1009

xxii
About the Author
Anghel Leonard is a Chief Technology Strategist and
independent consultant with 20+ years of experience in the
Java ecosystem. In his daily work, he focuses on architecting
and developing Java distributed applications that empower
robust architectures, clean code, and high-performance.
Anghel is also passionate about coaching, mentoring, and
technical leadership. He is the author of several books,
videos, and dozens of articles related to Java technologies.

xxiii
About the Technical Reviewer
Manuel Jordan Elera is an autodidactic developer and
researcher who enjoys learning new technologies for his
own experiments and creating new integrations. Manuel
won the Springy Award – Community Champion and Spring
Champion 2013. In his little free time, he reads the Bible
and composes music on his guitar. Manuel is known as
dr_pompeii. He has tech reviewed numerous books for
Apress, including Pro Spring Boot 2 (2019), Rapid Java
Persistence and Microservices (2019), Java Language
Features (2018), Spring Boot 2 Recipes (2018), and Java APIs,
Extensions and Libraries (2018). Read his 13 detailed tutorials about many Spring
technologies, contact him through his blog at http://www.manueljordanelera.
blogspot.com, and follow him on his Twitter account, @dr_pompeii.

xxv
Introduction
In a nutshell, this book is a collection of best practices for Java persistence performance
in Spring Boot applications. These practices have been exposed via 120+ items, and they
can be grouped into three categories:

• First, we discuss the best practices for defining entities, mapping


relationships, writing queries, fetching data, choosing identifiers
generators, and so on. Mainly, we cover the areas where Spring Boot
cannot help you with built-in artifacts and where you can avoid
important performance penalties that are hard to fix and may require
significant changes in your domain model.

• Second, we address best practices for using Spring Boot support


(more precisely, Spring Data). As you will see, relying on built-in
support as a silver bullet can come with performance penalties. For
example, using the Open Session in View, offset pagination, post-­
commits hooks, or misunderstanding @Transactional are just a few
of the covered topics. I’m pretty sure that you are ready and impatient
to jump into this category of items.

• Third, we deep dive into several Hibernate goodies that can sustain
the performance of your applications. By default, Spring Data relies
on Hibernate as its persistence provider, therefore you can exploit
Hibernate via Spring Data, and you can exploit underlying Hibernate
goodies as well. Goodies such as populating a child-side parent
association via a Hibernate proxy, using Dirty Tracking, delaying
connection acquisition, lazy loading attributes, and using natural
keys are just a few of the covered items.

The prerequisites of this book are pretty intuitive. You’ll need an IDE (e.g., NetBeans,
Eclipse, IntelliJ IDEA, Visual Studio, etc.), MySQL, and PostgreSQL. Optionally, you may
install or use other database vendors as well (e.g., Oracle, SQL Server, etc.).

xxvii
Random documents with unrelated
content Scribd suggests to you:
The Project Gutenberg eBook of The Passing
of Morocco
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.

Title: The Passing of Morocco

Author: Frederick Ferdinand Moore

Release date: October 12, 2021 [eBook #66521]

Language: English

Original publication: United States: Houghton Mifflin Company

Credits: D A Alexander, David E. Brown, and the librarians at South


Dakota State University for providing a high-res scan of the
map, and the Online Distributed Proofreading Team at
https://www.pgdp.net (This book was produced from
images made available by the HathiTrust Digital Library.)

*** START OF THE PROJECT GUTENBERG EBOOK THE PASSING OF


MOROCCO ***
THE PASSING OF MOROCCO
Frontispiece
.

A SAINT HOUSE.
THE
PASSING OF MOROCCO
BY
FREDERICK MOORE

AUTHOR OF ‘THE BALKAN TRAIL’

WITH ILLUSTRATIONS AND MAP

BOSTON AND NEW YORK


HOUGHTON, MIFFLIN, AND COMPANY
1908
TO
CHARLES TOWNSEND COPELAND
INTRODUCTION
For several years I had been watching Morocco as a man who
follows the profession of ‘Special Correspondent’ always watches a
place that promises exciting ‘copy.’ For many years trouble had been
brewing there. On the Algerian frontier tribes were almost constantly
at odds with the French; in the towns the Moors would now and
then assault and sometimes kill a European; round about Tangier a
brigand named Raisuli repeatedly captured Englishmen and other
foreigners for the sake of ransom; and among the Moors themselves
hardly a tribe was not at war with some other tribe or with the
Sultan. It was not, however, till July of last year that events assumed
sufficient importance to make it worth the while of a correspondent
to go to Morocco. Then, as fortune would have it, when the news
came that several Frenchmen had been killed at Casablanca and a
few days later that the town had been bombarded by French
cruisers, I was far away in my own country. It was ill-luck not to be
in London, five days nearer the trouble, for it was evident that this,
at last, was the beginning of a long, tedious, sometimes unclean
business, that would end eventually—if German interest could be
worn out—in the French domination of all North Africa west of
Tripoli.
Sailing by the first fast steamer out of New York I came to London,
and though late obtained a commission from the Westminster
Gazette. From here I went first to Tangier, viâ Gibraltar; then on to
Casablanca, where I saw the destruction of an Arab camp and also
witnessed the shooting of a party of prisoners; I visited Laraiche
against my will in a little ‘Scorpion’ steamer that put in there; and
finally spent some weeks at Rabat, the war capital, after Abdul Aziz
with his extraordinary following had come there from Fez.
Of these brief travels, covering all told a period of but three months,
and of events that are passing in the Moorish Empire this little book
is a record.

Six letters to the Westminster Gazette (forming parts of Chapters I.,


IV., VI., XIV., XV., and XVI.) are reprinted with the kind permission of
the Editor.
I have to thank Messrs. Forwood Bros., the Mersey Steamship
Company, for permission to reproduce the picture which appears on
the cover.
March 15, 1908.
CONTENTS
CHAPTER PAGE
Introduction vii-ix
I. Out of Gibraltar 1
II. Nights on a Roof 12
III. Dead Men and Dogs 30
IV. With the Foreign Legion 38
V. No Quarter 52
VI. The Holy War 59
VII. Forced Marches 71
VIII. Tangier 79
IX. Raisuli Protected by Great Britain 95
X. Down the Coast 102
XI. At Rabat 111
XII. The Pirate City of Salli 129
XIII. Many Wives 139
XIV. God Save the Sultan! 147
XV. Many Sultans 157
XVI. The British in Morocco 173
LIST OF ILLUSTRATIONS
A Saint House Frontispiece

To face page
Tangier Through the Kasbah Gate
10

The French War Balloon


An Algerian Spahi } ” 38

Arab Prisoners With a White Flag


A Column of the Foreign Legion } ” 60

On the Citadel, Tangier ” 80

A Riff Tribesman
A Maghzen Soldier } ” 96

The Castle at Laraiche ” 104

A Camp Outside the Walls of Rabat ” 126

Shawia Tribesmen ” 136

A Few of the Sultan’s Wives ” 144

Chained Neck To Neck: Recruits For the Sultan’s


Army
Abdul Aziz Entering His Palace
} ” 154
A Princely Kaid
The Royal Band } ” 162

Map of Morocco ” 188


THE PASSING OF MOROCCO
CHAPTER I
OUT OF GIBRALTAR
It was in August, 1907, one Tuesday morning, that I landed from a
P. & O. steamer at Gibraltar. I had not been there before but I knew
what to expect. From a distance of many miles we had seen the
Rock towering above the town and dwarfing the big, smoking men-
of-war that lay at anchor at its base. Ashore was to be seen ‘Tommy
Atkins,’ just as one sees him in England, walking round with a little
cane or standing stiff with bayonet fixed before a tall kennel, beside
him, as if for protection, a ‘Bobbie.’ The Englishman is everywhere in
evidence, always to be recognised, if not otherwise, by his stride—
which no one native to these parts could imitate. The Spaniard of
the Rock (whom the British calls contemptuously ‘Scorpion’) is
inclined to be polite and even gracious, though he struggles against
his nature in an attempt to appear ‘like English.’ Moors from over the
strait pass through the town and leisurely observe, without envying,
the Nasrani power, then pass on again, seeming always to say: ‘No,
this is not my country; I am Moslem.’ Gibraltar is thoroughly British.
Even the Jews, sometimes in long black gaberdines, seem foreign to
the place. And though on the plastered walls of Spanish houses are
often to be seen announcements of bull fights at Cordova and
Seville, the big advertisements everywhere are of such well-known
British goods as ‘Tatcho’ and ‘Dewar’s.’
I have had some wonderful views of the Rock of Gibraltar while
crossing on clear days from Tangier, and these I shall never forget,
but I think I should not like the town. No one associates with the
Spaniards, I am told, and the other Europeans, I imagine, are like
fish out of water. They seem to be of but two minds: those longing
to get back to England, and those who never expect to live at home
again. Most of the latter live and trade down the Moorish coast, and
come to ‘Gib’ on holidays once or twice a year, to buy some clothes,
to see a play, to have a ‘spree.’ Of course they are not ‘received’ by
the others, those who long for England, who are ‘exclusive’ and
deign to meet with only folk who come from home. In the old days,
when the Europeans in Morocco were very few, it was not unusual
for the lonesome exile to take down the coast with him from ‘Gib’ a
woman who was ‘not of the marrying brand.’ She kept his house and
sometimes bore him children. Usually after a while he married her,
but in some instances not till the children had grown and the sons in
turn began to go to Gibraltar.
My first stop at the Rock was for only an hour, for I was anxious to
get on to Tangier, and the little ‘Scorpion’ steamer that plied
between the ports, the Gibel Dursa, sailed that Tuesday morning at
eleven o’clock. I seemed to be the only cabin passenger, but on the
deck were many Oriental folk and low-caste Spaniards, not
uninteresting fellow-travellers. Though the characters of the North
African and the South Spaniard are said to be alike, in appearance
there could be no greater contrast, the one lean and long-faced, the
other round-headed and anxious always to be fat. Neither are they
at all alike in style of dress, and I had occasion to observe a peculiar
difference in their code of manners. I had brought aboard a quantity
of fresh figs and pears, more than I could eat, and I offered some to
a hungry-looking Spaniard, who watched me longingly; but he
declined. On the other hand a miserable Arab to whom I passed
them at once accepted and salaamed, though he told me by signs
that he was not accustomed to the sea and had eaten nothing since
he left Algiers. As I moved away, leaving some figs behind, I kept an
eye over my shoulder, and saw the Spaniard pounce upon them.
The conductor, or, as he would like to be dignified, the purser, of the
ship, necessarily a linguist, was a long, thin creature, sprung at the
knees and sunk at the stomach. He was of some outcast breed of
Moslem. Pock-marked and disfigured with several scars, his
appearance would have been repulsive were it not grotesque. None
of his features seemed to fit. His lips were plainly negro, his nose
Arabian, his ears like those of an elephant; I could not see his eyes,
covered with huge goggles, black enough to pale his yellow face.
Nor was this creature dressed in the costume of any particular race.
In place of the covering Moorish jeleba he wore a white duck coat
with many pockets. Stockings covered his calves, leaving only his
knees, like those of a Scot, visible below full bloomers of dark-green
calico. On his feet were boots instead of slippers. Of course this man
was noisy; no such mongrel could be quiet. He argued with the
Arabs and fussed with the Spaniards, speaking to each in their own
language. On spying me he came across the ship at a jump, grabbed
my hand and shook it warmly. He was past-master at the art of
identification. Though all my clothes including my hat and shoes had
come from England—and I had not spoken a word—he said at once,
‘You ’Merican man,’ adding, ‘No many ’Merican come Tangier now;
’fraid Jehad’—religious war.
‘Ah, you speak English,’ I said.
‘Yes, me speak Englis’ vera well: been ’Merica long time—Chicago,
New’leans, San ’Frisco, Balt’more, N’York’ (he pronounced this last
like a native). ‘Me been Barnum’s Circus.’
‘Were you the menagerie?’
The fellow was insulted. ‘No,’ he replied indignantly, ‘me was freak.’
Later when I had made my peace with him by means of a sixpence I
asked to be allowed to take his picture, at which he was much
flattered and put himself to the trouble of donning a clean coat;
though, in order that no other Mohammedan should see and vilify
him, he would consent to pose only on the upper-deck.
Sailing from under the cloud about Gibraltar the skies cleared
rapidly, and in less than half-an-hour the yellow hills of the shore
across the strait shone brilliantly against a clear blue sky. There was
no mistaking this bit of the Orient. For an hour we coasted through
the deep green waters. Before another had passed a bleak stretch of
sand, as from the Sahara, came down to the sea; and there beyond,
where the yellow hills began again, was the city of Tangier, the
outpost of the East. A mass of square, almost windowless houses,
blue and white, climbing in irregular steps, much like the ‘Giant’s
Causeway,’ to the walls of the ancient Kasbah, with here and there a
square green minaret or a towering palm.
We dropped anchor between a Spanish gunboat and the six-
funnelled cruiser Jeanne d’Arc, amid a throng of small boats rowed
by Moors in coloured bloomers, their legs and faces black and white
and shades between. While careful to keep company with my
luggage, I managed at the same time to embark in the first boat,
along with the mongrel in the goggles and a veiled woman with
three children, as well as others. Standing to row and pushing their
oars, the bare-legged boatmen took us rapidly towards the landing—
then to stop within a yard of the pier and for a quarter of an hour
haggle over fares. Three reals Moorish was all they could extort from
the Spaniards, and this was the proper tariff; but from me two
pesetas, three times as much, was exacted. I protested, and got the
explanation, through the man of many tongues, that this was the
regulation charge for ‘landing’ Americans. In this country, he added
from his own full knowledge, the rich are required to pay double
where the poor cannot. While the Spaniards, the freak and I climbed
up the steps to the pier, several boatmen, summoned from the quay,
came wading out and took the woman and her children on their
backs, landing them beyond the gate where pier-charges of a real
are paid.
At the head of the pier a rickety shed of present-day construction,
supported by an ancient, crumbling wall, is the custom-house. Not in
anticipation of difficulty here, but as a matter of precaution, I had
stuffed into my pockets (knowing that my person could not be
searched) my revolver and a few books; and to hide these I wore a
great-coat and sweltered in it. Perhaps from my appearance the
cloaked Moors, instead of realising the true reason, only considered
me less mad than the average of my kind. At any rate they ‘passed’
me bag and baggage with a most superficial examination and not
the suggestion that backsheesh would be acceptable.
But on another day I had a curious experience at this same custom-
house. A new kodak having followed me from London was held for
duty, which should be, according to treaty, ten per cent. ad valorem.
It was in no good humour that after an hour’s wrangling I was finally
led into a room with a long rough table at the back and four
spectacled, grey-bearded Moors in white kaftans and turbans seated
behind.
‘How much?’ I asked and a Frenchman translated.
‘Four dollars,’ came the reply.
‘The thing is only worth four pounds twenty dollars; I’ll give you one
dollar.’
‘Make it three—three dollars, Hassani.’
‘No, one.’
‘Make it two—two dollars Spanish.’
This being the right tax, I paid. But I was not to get my goods yet;
what was my name?
TANGIER THROUGH THE KASBAH GATE.
‘Moore.’
‘No, your name.’
‘I presented my card.’
‘Moore!’ A laugh went down the turbaned line.
A writer on the East has said of the Moors that they are the Puritans
of Islam, and the first glimpse of Morocco will attest the truth of this.
Not a Moor has laid aside the jeleba and the corresponding
headgear, turban or fez. In the streets of Tangier—of all Moorish
towns the most ‘contaminated’ with Christians—there is not a
tramway or a hackney cab. Not a railway penetrates the country
anywhere, not a telegraph, nor is there a postal service. Except for
the discredited Sultan (whose ways have precipitated the disruption
of the Empire) not a Moor has tried the improvements of Europe. It
seems extraordinary that such a country should be the ‘Farthest
West of Islam’ and should face the Rock of Gibraltar.
CHAPTER II
NIGHTS ON A ROOF

I did not stop long on this occasion at Tangier, because, from a


newspaper point of view, Casablanca was a place of more immediate
interest. The night before I sailed there arrived an old Harvard friend
travelling for pleasure, and he proposed to accompany me. Johnny
Weare was a young man to all appearances accustomed to good
living, and friends of an evening—easy to acquire at Tangier—
advised him to take a supply of food. But I unwisely protested and
dissuaded John, and we went down laden with little unnecessary
luggage, travelling by a French torpedo-boat conveying despatches.
Here I must break my story in order to make it complete, and
anticipate our arrival at Casablanca with an account of how the
French army happened to be lodged in this Moorish town. In 1906 a
French company obtained a contract from the Moorish Government
to construct a harbour at Casablanca; and beginning work they
found it expedient, in order to bring up the necessary stone and
gravel, to lay a narrow-gauge railway to a quarry a few miles down
the coast. In those Mohammedan countries where the dead are
protected from ‘Infidel’ tread the fact that the tracks bordered close
on a cemetery, in fact passed over several graves, would have been
cause perhaps for a conflict; but this—though enemies of France
have tried to proclaim it—was not a serious matter in Morocco,
where the Moslems are done with their dead when they bury them
and anyone may walk on the graves. The French were opposed
solely because they were Christian invaders to whom the Sultan had
‘sold out.’ They had bought the High Shereef with their machines
and their money, but the tribes did not intend to tolerate them.
After many threats the Arabs of the country came to town one
market-day prepared for war. Gathering the local Moors, including
those labouring on the railway, they surrounded and killed in brutal
fashion, with sticks and knives and the butts of guns, the engineer
of the locomotive and eight other French and Italian workmen. The
French cruiser Galilée was despatched to the scene, and arriving two
days later lay in harbour apparently awaiting instructions from home.
By this delay the Moors, though quiet, were encouraged, hourly
becoming more convinced that if the French could land they would
have done so. They were thoroughly confident, as their resistance
demonstrated, when, after three days, a hundred marines were put
ashore. As the marines passed through the ‘Water Port’ they were
fired upon by a single Moor, and thereupon they shot at every
cloaked man that showed his head on their march of half-a-mile to
the French consulate. At the sound of rifles the Galilée began
bombarding the Moslem quarters of the town; and the stupid
Moorish garrison, with guns perhaps brought out of Spain, essayed
to reply, and lasted for about ten minutes.
But the landing force of the French was altogether too small to do
more than protect the French consulate and neighbouring European
houses. Town Moors and Arabs turned out to kill and rape and loot,
as they do whenever opportunity offers, and for three days they
plundered the places of Europeans and Jews and at last fought
among themselves for the spoils until driven from the town by
reinforcements of French and Spanish troops.
The fighting and the shells from French ships had laid many bodies
in the streets and had wrecked many houses and some mosques.
Certain Moors, less ignorant of the French power, had asked the
French to spare the mosques and the ‘Saint Houses,’ domed tombs
of dead shereefs, and when the fighting began the Arabs, seeing
these places were untouched, concluded, of course, that the
protection came from Allah, until they entered them and drew the
French fire.
Casablanca, or, as the Arabs call it, Dar el Baida, ‘White House,’ was
a desolate-looking place when we arrived three weeks after the
bombardment. Hardly a male Moor was to be seen. The whole
Moslem population, with the exception of a few men of wealth who
enjoy European protection, and some servants of consulates, had
deserted the town and had not yet begun to return. Jews in black
caps and baggy trousers were the only labourers, and they worked
with a will recovering damaged property at good pay, and grinning
at their good fortune. In the attack the Moors had driven them to
the boats, but now the Moors themselves had had to go. Native
Spaniards did the lighter work.
A Spaniard and a Jewish boy took our luggage to an hotel, of which
all the rooms were already occupied, even to the bathroom and the
wine closet, as the long zinc tub in the courtyard, filled with bottles,
testified. The proprietor told us that for ten francs a day we might
have the dining-room to sleep in, but on investigation we decided to
hunt further. Speaking Spanish with a grand manner, for he was a
cavalier fellow, the hotel-keeper then informed us through an
interpreter that he wanted to do what he could for us because he
too was an American. The explanation (for which we asked) was
that in New York he had a brother whom he had once visited for a
few months, and that at that time, ‘to favour an American
gentleman,’ he had taken out naturalisation papers and voted for the
mayor.
But this man’s breach of the law in New York was his mildest sin, as
we came later to hear. He had many robberies to his credit and a
murder or two. For his latest crime he was now wanted by the
French consul and military authorities, but being an American citizen
they could not lay hold of him except with the consent of the
American consul, who happened to be a German, and, disliking the
French, would let them do nothing that he could help. Rodrigues
(this was the name of the Spanish caballero) had defended his place
against the Arab attack with the aid only of his servants. The little
arsenal which he kept (he was a fancier of good guns and pistols)
had been of splendid service. It is said that when the fight was over
forty dead Moors lay before the hotel door, half-a-dozen horses were
in Rodrigues’s stable, and bundles of plunder in his yard. It was a
case of looting the looters. On tinned foods taken from the shops of
other Europeans (whom he had plundered when the Arabs were
gone from the town) he was now feeding the host of newspaper
correspondents who crowded his establishment. But we were not to
be looted likewise by this genial fellow-countryman, and our
salvation lay at hand as we bade him au revoir.
Leaving the Hôtel Américain we turned into the main street, and
proceeding towards the Hôtel Continental came upon a party of
French officers, who had just hailed and were shaking hands with a
man unmistakably either English or American. Beside him, even in
their military uniforms the Frenchmen were insignificant. The other
man was tall and splendid and brave, as the writer of Western fiction
would say. He wore a khaki jacket, white duck riding trousers,
English leggings, and a cowboy hat; and over one shoulder were
slung a rifle, a kodak, and a water-bottle. To lend reality to the
figure—he was dusty, and his collar was undone; and as we passed
the group we heard him tell the Frenchmen he had just returned
from the ‘outer lines.’ How often had we seen the picture of this
man, the war correspondent of fiction and of kodak advertisements!
Both Weare and I were glad to meet the old familiar friend in the
flesh and wanted to speak to him, but we refrained for fear he might
be English and might resent American effrontery. As we passed him,
however, we noticed his name across the flat side of the water-
bottle. In big, bold letters was the inscription: ‘Captain Squall,
Special War Correspondent of “The Morning Press.”’ This was
characteristic of Squall, as we came to know; neither ‘special
correspondent’ nor ‘war correspondent’ was a sufficient title for him;
he must be ‘special war correspondent.’
We had heard of Squall at Tangier and thought we could stop and
speak to him, and accordingly waited a moment till he had left the
Frenchmen. ‘How-do-you-do, Captain?’ I said. ‘I have an introduction
to you in my bag from the correspondent of your paper at Tangier.’
‘You’re an American,’ was the Captain’s first remark, not a very novel
observation; ‘I’ve been in America a good deal myself.’ He adjusted a
monocle and explained with customary originality that he had one
bad eye. ‘What do you think of my “stuff” in the Press?’ was his next
remark.
‘A little personal, isn’t it? I read that despatch about your being
unable to get any washing done at the hotel because of scarcity of
water, and your leaving it for that reason.’
‘Yes, that’s what the British public like to read, personal touches,
don’t you think?’
‘Where are you living now? We have to find a place.’
‘Come with me. You know the Americans were always very
hospitable to me, and I like to have a chance to do them a good
turn. I’m living on a roof and getting my own grub. You know I’m an
old campaigner—I mean to say, I’ve been in South Africa, and on the
Canadian border, and I got my chest smashed in by a Russian in the
Japanese war,—I mean a hand to hand conflict, you know, using the
butts of our guns.’
‘Were you a correspondent out there?’
‘No, I was fighting for the Japs; I’m a soldier of fortune, you know.’
‘But the Japanese Government did not allow Europeans to enlist.’
‘I was the only one they would enlist; I mean to say, my father had
some influence with the Japanese minister in London.’
‘But you’re very young; how old are you?’
‘Well, I don’t like to say; I mean there’s a reason I can’t tell my age,
—I mean, I went to South Africa when I was sixteen; you see that’s
under age for military service in the British Army.’ The Captain
waited a moment, then started off again. ‘I’ve got medals from five
campaigns.’
‘I’d like to see them.’
Indifferently he opened his jacket.
‘There are six,’ I remarked.
‘Oh, that’s not a campaign medal; that’s a medal of the Legion of
Frontiersmen. I mean to say, I was one of the organisers of that.’
Weare and I recognised the type. There are many of them abroad
and some wear little American flags. But, of course, to us they are
more grotesque when they affect the monocle. We knew Squall
would not be insulted if we turned the conversation to the matter of
most interest to us at that moment.
‘For my part,’ said Weare, ‘I could do well with something to eat just
now. One doesn’t eat much on a torpedo-boat.’
With the prospects of our companionship—for Squall was boycotted
by most of the correspondents—he led us away to his roof to get us
a meal; and, for what the town provided, a good meal he served us.
He did his own cooking, but he did it because he liked to cook,—he
meant to say, he had money coming to him from the sale of a
motor-car in London, and he had just lost fifteen or twenty thousand
pounds—the exact amount did not matter either to us or to him.
For a fortnight, till an old American resident of Casablanca invited us
to his house, we suffered Squall. We three slept on the roof while a
decrepit, dirty Spaniard, the owner of the place, slept below. It was
a modest, one-storey house, built in Moorish style. There were
rooms on four sides of a paved courtyard, under a slab in the centre
of which was the customary well. Overhead a covering of glass, now
much broken, was intended to keep out the rain. The place had
been looted by the Moors, who took away the few things of any
value and destroyed the rest, leaving the room littered with torn
clothes and bedding and broken furniture, if I might dignify the stuff
by these names; nor had the old man (whose family had escaped to
Tangier) cleared out any place but the kitchen and the courtyard.
There was a little slave boy whose master had been killed, and who
now served a ‘Mister Peto’ and came to us for water every day. As
our old Spaniard would not keep the place clean and saved all the
food that we left from meals (which filled the place with flies) we
hired the boy for a peseta, about a franc, a day to keep it clean. He
was to get nothing at all if he allowed in more than twenty-five flies,
and for one day he worked well and got the money. But the reason
of his success was the presence all that day of one or the other of us
engaged at writing, protecting him from the wrath of the old man,
who resented being deprived of both stench and flies. The next day
when we returned from the French camp there was no more black
boy, and we never saw him again, nor could we ascertain from the
old man what had happened to him. Thereafter we never drew a
bucket of drinking water from the well without the fear of bringing
up a piece of poor ‘Sandy.’
As candles were scarce and bad we went to bed early. Weare and I
generally retiring first. We climbed the rickety, ladder-like stairs and
walked round the glass square over the courtyard to the side of the
roof where cooling breezes blew from the Atlantic. There undressing,
we rolled our clothes in tight bundles and put them under our heads
for pillows. To lie on we had only sacking, for our rain-coats had to
be used as covering to keep off the heavy dews of the early
morning. Only Squall had a hammock.
Before retiring every evening Squall had the task of examining and
testing his weapons, of which he had enough for us all. A ‘Webley’
and ‘Colt’ were not sufficient, he must also bring to the roof his rifle,
on the butt of which were fourteen notches, one for each Moor he
had shot. He clanked up the steps like Long John, the pirate, coming
from ‘below,’ in ‘Treasure Island.’ When he had got into the
hammock, lying comfortably on revolvers and cartridge belts, his
gun within reach against the wall, he would begin to talk. ‘You chaps
think I bring all these “shooting-irons” up here because I’m afraid of
something. Only look at what I’ve been through. I’ve got over being
afraid. The reason I bring them all up with me is that I don’t want
them stolen,—I mean to say there isn’t any lock on the door, you
know.’
‘Go to sleep, Squall.’
‘I mean you chaps haven’t got any business talking about me being
afraid.’
‘Can’t you tell us about it at breakfast, Squall?’
One night Squall wanted to borrow a knife; his, he said, was not
very sharp. He had been out ‘on the lines’ that day, and he wanted
it, he explained, to put another notch in his gun.
Sometimes a patrol would pass in the night, and we would hear the
three pistols and the gun click. Once the gun went off.
At daybreak we would rouse old Squall to go and make coffee, and
while he was thus employed we were entertained by the occupants
of a ‘kraal’ (I can think of no better description) next door. In a little,
low hut, built of reeds and brush, directly under our roof, lived a
dusky mother and her daughter. The one (I imagine) was a widow,
the other an unmarried though mature maid. They were among the
score of Moors who had not fled, and there being no men of their
own race about they were not afraid to show their faces to us. The
mother was a hag, but the younger woman was splendid, big and
broad-shouldered, with a deep chest. Her colour was that of an
Eastern gipsy, bronze as if sunburned, with a slight red in her
cheeks; she was black-haired, and she always wore a flower. From
her lower lip to her chin was a double line tattooed in blue, and
about her ankles and arms, likewise tattooed, were broad blue
bangles, one above her elbow. The clothes that she wore, though of
common cotton, were brilliant in colour, generally bright green or
blue or orange-yellow, sometimes a combination; they were not
made into garments but rather draped about her, as is the way in
Morocco, and held together with gaudy metal ornaments. Two bare
feet, slippered in red, and one bare arm and shoulder were always
visible. While this younger woman cooked in the open yard, and the
old crone lean and haggard watched, they would look up from their
kettle from time to time and speak to us in language we could not
understand. We threw them small coins and they offered us tea. But
we did not visit the ladies, to run the risk, perhaps, of dissipating an
illusion.
‘Coffee, you chaps,’ sounded from below, and we went down to
breakfast with good old ‘Blood-stained Bill.’

You might also like