or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/maven-org-springframework-boot--spring-boot-starter-data-jpa

Starter for using Spring Data JPA with Hibernate

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.springframework.boot/spring-boot-starter-data-jpa@3.5.x

To install, run

npx @tessl/cli install tessl/maven-org-springframework-boot--spring-boot-starter-data-jpa@3.5.0

0

# Spring Boot Starter Data JPA

1

2

Spring Boot Starter Data JPA provides comprehensive auto-configuration for integrating Spring Data JPA with Hibernate ORM in Spring Boot applications. This starter automatically configures JPA EntityManagerFactory, transaction management, repository support, and Hibernate-specific settings, enabling developers to build data access layers with minimal configuration.

3

4

## Package Information

5

6

- **Package Name**: spring-boot-starter-data-jpa

7

- **Package Type**: maven

8

- **Maven Coordinates**: org.springframework.boot:spring-boot-starter-data-jpa

9

- **Language**: Java

10

- **Framework**: Spring Boot 3.5.0

11

- **Installation**: Add dependency to `pom.xml` or `build.gradle`

12

13

**Maven**:

14

```xml

15

<dependency>

16

<groupId>org.springframework.boot</groupId>

17

<artifactId>spring-boot-starter-data-jpa</artifactId>

18

<version>3.5.0</version>

19

</dependency>

20

```

21

22

**Gradle**:

23

```gradle

24

implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.5.0'

25

```

26

27

## Core Imports

28

29

```java

30

import org.springframework.data.jpa.repository.JpaRepository;

31

import org.springframework.boot.autoconfigure.orm.jpa.*;

32

import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;

33

import jakarta.persistence.*;

34

```

35

36

## Basic Usage

37

38

```java

39

// 1. Define an entity

40

@Entity

41

@Table(name = "users")

42

public class User {

43

@Id

44

@GeneratedValue(strategy = GenerationType.IDENTITY)

45

private Long id;

46

47

@Column(nullable = false)

48

private String name;

49

50

private String email;

51

52

// Getters and setters

53

}

54

55

// 2. Create a repository interface (Spring Data JPA auto-implements it)

56

public interface UserRepository extends JpaRepository<User, Long> {

57

List<User> findByName(String name);

58

Optional<User> findByEmail(String email);

59

}

60

61

// 3. Use the repository in a service

62

@Service

63

public class UserService {

64

private final UserRepository userRepository;

65

66

public UserService(UserRepository userRepository) {

67

this.userRepository = userRepository;

68

}

69

70

public User createUser(String name, String email) {

71

User user = new User();

72

user.setName(name);

73

user.setEmail(email);

74

return userRepository.save(user);

75

}

76

77

public List<User> findUsersByName(String name) {

78

return userRepository.findByName(name);

79

}

80

}

81

82

// 4. Configure database connection in application.properties

83

// spring.datasource.url=jdbc:postgresql://localhost:5432/mydb

84

// spring.datasource.username=dbuser

85

// spring.datasource.password=dbpass

86

// spring.jpa.hibernate.ddl-auto=update

87

// spring.jpa.show-sql=true

88

```

89

90

## Architecture

91

92

The starter provides several layers of auto-configuration:

93

94

- **Auto-Configuration Layer**: `HibernateJpaAutoConfiguration` and `JpaRepositoriesAutoConfiguration` automatically detect dependencies and configure beans

95

- **JPA Configuration**: `JpaBaseConfiguration` provides EntityManagerFactory, TransactionManager, and related infrastructure beans

96

- **Repository Support**: Spring Data JPA repositories are automatically enabled and implemented

97

- **Hibernate Integration**: Hibernate-specific configuration including naming strategies, DDL handling, and JTA platform

98

- **Customization Layer**: Extensible through properties, customizer interfaces, and bean overrides

99

100

## Capabilities

101

102

### Auto-Configuration

103

104

The starter automatically configures JPA and Hibernate when dependencies are detected on the classpath.

105

106

**Auto-Configuration Classes**:

107

108

```java { .api }

109

@AutoConfiguration(

110

after = { DataSourceAutoConfiguration.class, TransactionManagerCustomizationAutoConfiguration.class },

111

before = { TransactionAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class }

112

)

113

@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class, SessionImplementor.class })

114

@EnableConfigurationProperties(JpaProperties.class)

115

@Import(HibernateJpaConfiguration.class)

116

public class HibernateJpaAutoConfiguration {

117

// Auto-configures Hibernate as the JPA provider

118

// Imports HibernateJpaConfiguration

119

}

120

121

/**

122

* Base configuration for JPA. Provides EntityManagerFactory, TransactionManager,

123

* and OpenEntityManagerInView support.

124

* Package: org.springframework.boot.autoconfigure.orm.jpa

125

*/

126

@Configuration(proxyBeanMethods = false)

127

@EnableConfigurationProperties(JpaProperties.class)

128

public abstract class JpaBaseConfiguration {

129

/**

130

* Create a JpaBaseConfiguration instance.

131

*

132

* @param dataSource The DataSource to use

133

* @param properties JPA configuration properties

134

* @param jtaTransactionManager Optional JTA transaction manager

135

*/

136

protected JpaBaseConfiguration(

137

DataSource dataSource,

138

JpaProperties properties,

139

ObjectProvider<JtaTransactionManager> jtaTransactionManager

140

) { }

141

142

/**

143

* Configure the JPA transaction manager.

144

*

145

* @param transactionManagerCustomizers Optional customizers

146

* @return The configured PlatformTransactionManager

147

*/

148

@Bean

149

@ConditionalOnMissingBean(TransactionManager.class)

150

public PlatformTransactionManager transactionManager(

151

ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers

152

) { }

153

154

/**

155

* Create the primary EntityManagerFactory bean.

156

*

157

* @param factoryBuilder EntityManagerFactoryBuilder for creating the factory

158

* @param persistenceManagedTypes Auto-scanned entity types

159

* @return LocalContainerEntityManagerFactoryBean

160

*/

161

@Bean

162

@Primary

163

@ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class, EntityManagerFactory.class })

164

public LocalContainerEntityManagerFactoryBean entityManagerFactory(

165

EntityManagerFactoryBuilder factoryBuilder,

166

PersistenceManagedTypes persistenceManagedTypes

167

) { }

168

169

/**

170

* Create an EntityManagerFactoryBuilder bean.

171

*

172

* @param jpaVendorAdapter JPA vendor adapter

173

* @param persistenceUnitManager Optional persistence unit manager

174

* @param customizers Customizers for the builder

175

* @return EntityManagerFactoryBuilder instance

176

*/

177

@Bean

178

@ConditionalOnMissingBean

179

public EntityManagerFactoryBuilder entityManagerFactoryBuilder(

180

JpaVendorAdapter jpaVendorAdapter,

181

ObjectProvider<PersistenceUnitManager> persistenceUnitManager,

182

ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers

183

) { }

184

185

/**

186

* Return the vendor-specific properties for the given DataSource.

187

*

188

* @param dataSource The data source

189

* @return Map of vendor-specific properties

190

* @since 3.4.4

191

*/

192

protected abstract Map<String, Object> getVendorProperties(DataSource dataSource);

193

194

/**

195

* Return the vendor-specific properties.

196

*

197

* @return Map of vendor-specific properties

198

* @deprecated since 3.4.4 for removal in 4.0.0 in favor of getVendorProperties(DataSource)

199

*/

200

@Deprecated(since = "3.4.4", forRemoval = true)

201

protected Map<String, Object> getVendorProperties() { }

202

203

/**

204

* Customize vendor properties before they are used. Allows for post-processing

205

* (for example to configure JTA-specific settings).

206

*

207

* @param vendorProperties The vendor properties to customize

208

*/

209

protected void customizeVendorProperties(Map<String, Object> vendorProperties) { }

210

211

/**

212

* Return the JTA transaction manager.

213

*

214

* @return The transaction manager or null if not using JTA

215

*/

216

protected JtaTransactionManager getJtaTransactionManager() { }

217

218

/**

219

* Returns if a JTA PlatformTransactionManager is being used.

220

*

221

* @return true if a JTA transaction manager is being used

222

*/

223

protected final boolean isJta() { }

224

225

/**

226

* Create and configure the JPA vendor adapter bean.

227

* Configures the adapter with showSql, database, databasePlatform, and generateDdl settings.

228

*

229

* @return Configured JPA vendor adapter

230

*/

231

@Bean

232

@ConditionalOnMissingBean

233

public JpaVendorAdapter jpaVendorAdapter() { }

234

235

/**

236

* Return the JpaProperties.

237

*

238

* @return The JPA properties

239

*/

240

protected final JpaProperties getProperties() { }

241

242

/**

243

* Return the DataSource.

244

*

245

* @return The data source

246

*/

247

protected final DataSource getDataSource() { }

248

249

// Abstract methods that must be implemented by subclasses

250

protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();

251

252

/**

253

* Configuration for PersistenceManagedTypes bean.

254

* Automatically scans for JPA entities in specified packages.

255

* Package: org.springframework.boot.autoconfigure.orm.jpa

256

*/

257

@Configuration(proxyBeanMethods = false)

258

@ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class, EntityManagerFactory.class })

259

static class PersistenceManagedTypesConfiguration {

260

/**

261

* Create PersistenceManagedTypes bean by scanning for entity classes.

262

* Scans packages from @EntityScan or auto-configuration packages.

263

*

264

* @param beanFactory Bean factory for accessing configuration

265

* @param resourceLoader Resource loader for scanning

266

* @param managedClassNameFilter Optional filter for entity class names

267

* @return PersistenceManagedTypes containing discovered entity types

268

*/

269

@Bean

270

@Primary

271

@ConditionalOnMissingBean

272

static PersistenceManagedTypes persistenceManagedTypes(

273

BeanFactory beanFactory,

274

ResourceLoader resourceLoader,

275

ObjectProvider<ManagedClassNameFilter> managedClassNameFilter

276

) { }

277

}

278

279

/**

280

* Configuration for OpenEntityManagerInView pattern support in web applications.

281

* Registers interceptor to bind JPA EntityManager to request thread.

282

* Package: org.springframework.boot.autoconfigure.orm.jpa

283

*/

284

@Configuration(proxyBeanMethods = false)

285

@ConditionalOnWebApplication(type = Type.SERVLET)

286

@ConditionalOnClass(WebMvcConfigurer.class)

287

@ConditionalOnMissingBean({ OpenEntityManagerInViewInterceptor.class, OpenEntityManagerInViewFilter.class })

288

@ConditionalOnMissingFilterBean(OpenEntityManagerInViewFilter.class)

289

@ConditionalOnBooleanProperty(name = "spring.jpa.open-in-view", matchIfMissing = true)

290

protected static class JpaWebConfiguration {

291

/**

292

* Create JpaWebConfiguration instance.

293

*

294

* @param jpaProperties JPA configuration properties

295

*/

296

protected JpaWebConfiguration(JpaProperties jpaProperties) { }

297

298

/**

299

* Create OpenEntityManagerInView interceptor bean.

300

* Logs warning if spring.jpa.open-in-view is not explicitly configured.

301

*

302

* @return OpenEntityManagerInViewInterceptor instance

303

*/

304

@Bean

305

public OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor() { }

306

307

/**

308

* Create WebMvcConfigurer to register the OpenEntityManagerInView interceptor.

309

*

310

* @param interceptor The interceptor to register

311

* @return WebMvcConfigurer that registers the interceptor

312

*/

313

@Bean

314

public WebMvcConfigurer openEntityManagerInViewInterceptorConfigurer(

315

OpenEntityManagerInViewInterceptor interceptor

316

) { }

317

}

318

}

319

320

/**

321

* Auto-configuration for Spring Data JPA repositories.

322

* Package: org.springframework.boot.autoconfigure.data.jpa

323

*/

324

@AutoConfiguration(after = { HibernateJpaAutoConfiguration.class, TaskExecutionAutoConfiguration.class })

325

@ConditionalOnBean(DataSource.class)

326

@ConditionalOnClass(JpaRepository.class)

327

@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class, JpaRepositoryConfigExtension.class })

328

@ConditionalOnBooleanProperty(name = "spring.data.jpa.repositories.enabled", matchIfMissing = true)

329

@Import(JpaRepositoriesImportSelector.class)

330

public class JpaRepositoriesAutoConfiguration {

331

/**

332

* Configure EntityManagerFactory bootstrap executor for deferred/lazy initialization.

333

*

334

* @param taskExecutors Available async task executors

335

* @return EntityManagerFactoryBuilderCustomizer

336

*/

337

@Bean

338

@Conditional(BootstrapExecutorCondition.class)

339

public EntityManagerFactoryBuilderCustomizer entityManagerFactoryBootstrapExecutorCustomizer(

340

Map<String, AsyncTaskExecutor> taskExecutors

341

) { }

342

343

/**

344

* Import selector that chooses the appropriate repository registrar.

345

* Selects EnversRevisionRepositoriesRegistrar if Hibernate Envers is on the classpath,

346

* otherwise selects JpaRepositoriesRegistrar.

347

*/

348

static class JpaRepositoriesImportSelector implements ImportSelector {

349

/**

350

* Select which repository configuration class to import.

351

* Returns EnversRevisionRepositoriesRegistrar if Envers is available,

352

* otherwise returns JpaRepositoriesRegistrar.

353

*

354

* @param importingClassMetadata Metadata of the importing class

355

* @return Array containing the fully qualified name of the registrar class to import

356

*/

357

@Override

358

public String[] selectImports(AnnotationMetadata importingClassMetadata) { }

359

}

360

}

361

```

362

363

**Beans Created by Auto-Configuration**:

364

365

- `entityManagerFactory` (LocalContainerEntityManagerFactoryBean) - Primary JPA EntityManagerFactory

366

- `transactionManager` (JpaTransactionManager) - Transaction manager for JPA operations

367

- `jpaVendorAdapter` (HibernateJpaVendorAdapter) - Hibernate vendor adapter

368

- `entityManagerFactoryBuilder` (EntityManagerFactoryBuilder) - Builder for additional EntityManagerFactory instances

369

- `persistenceManagedTypes` (PersistenceManagedTypes) - Auto-scanned entity types

370

- `openEntityManagerInViewInterceptor` (OpenEntityManagerInViewInterceptor) - Request-scoped EntityManager binding (web apps)

371

372

### Configuration Properties

373

374

Configure JPA and Hibernate behavior through `application.properties` or `application.yml`.

375

376

#### JPA Properties (spring.jpa.*)

377

378

```java { .api }

379

@ConfigurationProperties(prefix = "spring.jpa")

380

public class JpaProperties {

381

// spring.jpa.properties - Additional JPA/Hibernate properties

382

private Map<String, String> properties = new HashMap<>();

383

384

// spring.jpa.mapping-resources - Persistence XML mapping files

385

private final List<String> mappingResources = new ArrayList<>();

386

387

// spring.jpa.database-platform - Database dialect class name

388

private String databasePlatform;

389

390

// spring.jpa.database - Target database enum (AUTO-DETECTED by default)

391

private Database database;

392

393

// spring.jpa.generate-ddl - Initialize schema on startup (default: false)

394

private boolean generateDdl = false;

395

396

// spring.jpa.show-sql - Enable SQL logging (default: false)

397

private boolean showSql = false;

398

399

// spring.jpa.open-in-view - Enable OpenEntityManagerInView pattern (default: true)

400

private Boolean openInView;

401

402

// Getter and setter methods

403

public Map<String, String> getProperties() { }

404

public void setProperties(Map<String, String> properties) { }

405

406

public List<String> getMappingResources() { }

407

408

public String getDatabasePlatform() { }

409

public void setDatabasePlatform(String databasePlatform) { }

410

411

public Database getDatabase() { }

412

public void setDatabase(Database database) { }

413

414

public boolean isGenerateDdl() { }

415

public void setGenerateDdl(boolean generateDdl) { }

416

417

public boolean isShowSql() { }

418

public void setShowSql(boolean showSql) { }

419

420

public Boolean getOpenInView() { }

421

public void setOpenInView(Boolean openInView) { }

422

423

// Note: spring.jpa.defer-datasource-initialization is not in JpaProperties class

424

// It's a separate property handled by Spring Boot's database initialization system

425

// spring.jpa.defer-datasource-initialization - Defer DataSource initialization

426

// until after EntityManagerFactory beans are created (default: false)

427

}

428

```

429

430

**Common Configuration Examples**:

431

432

```properties

433

# Database connection

434

spring.datasource.url=jdbc:postgresql://localhost:5432/mydb

435

spring.datasource.username=user

436

spring.datasource.password=pass

437

438

# JPA settings

439

spring.jpa.show-sql=true

440

spring.jpa.open-in-view=false

441

spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

442

443

# Defer datasource initialization until after JPA is ready

444

# Useful when using script-based initialization with JPA schema generation

445

spring.jpa.defer-datasource-initialization=false

446

447

# Additional Hibernate properties

448

spring.jpa.properties.hibernate.format_sql=true

449

spring.jpa.properties.hibernate.use_sql_comments=true

450

spring.jpa.properties.hibernate.jdbc.batch_size=20

451

```

452

453

#### Hibernate Properties (spring.jpa.hibernate.*)

454

455

```java { .api }

456

@ConfigurationProperties(prefix = "spring.jpa.hibernate")

457

public class HibernateProperties {

458

// spring.jpa.hibernate.ddl-auto - DDL mode (none, validate, update, create, create-drop)

459

private String ddlAuto;

460

461

// Nested naming configuration

462

private Naming naming = new Naming();

463

464

/**

465

* Get the DDL auto mode.

466

*

467

* @return The DDL auto mode

468

*/

469

public String getDdlAuto() { }

470

471

/**

472

* Set the DDL auto mode.

473

*

474

* @param ddlAuto The DDL auto mode to set

475

*/

476

public void setDdlAuto(String ddlAuto) { }

477

478

/**

479

* Get the naming strategy configuration.

480

*

481

* @return The naming configuration

482

*/

483

public Naming getNaming() { }

484

485

/**

486

* Determine Hibernate configuration properties based on JPA properties and settings.

487

*

488

* @param jpaProperties Standard JPA properties

489

* @param settings Hibernate-specific settings

490

* @return Map of Hibernate properties to use

491

*/

492

public Map<String, Object> determineHibernateProperties(

493

Map<String, String> jpaProperties,

494

HibernateSettings settings

495

) { }

496

497

/**

498

* Nested class for Hibernate naming strategy configuration.

499

*/

500

public static class Naming {

501

// spring.jpa.hibernate.naming.implicit-strategy - Implicit naming strategy class

502

private String implicitStrategy;

503

504

// spring.jpa.hibernate.naming.physical-strategy - Physical naming strategy class

505

private String physicalStrategy;

506

507

public String getImplicitStrategy() { }

508

public void setImplicitStrategy(String implicitStrategy) { }

509

public String getPhysicalStrategy() { }

510

public void setPhysicalStrategy(String physicalStrategy) { }

511

}

512

}

513

```

514

515

**DDL Auto Values**:

516

- `none` - No schema management

517

- `validate` - Validate schema matches entities (production)

518

- `update` - Update schema to match entities (development)

519

- `create` - Drop and recreate schema on startup

520

- `create-drop` - Drop schema on shutdown

521

522

**Default Naming Strategies**:

523

- Implicit: `org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy`

524

- Physical: `org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy`

525

526

**Configuration Examples**:

527

528

```properties

529

# Schema management

530

spring.jpa.hibernate.ddl-auto=update

531

532

# Custom naming strategies

533

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

534

spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

535

```

536

537

#### Repository Properties (spring.data.jpa.repositories.*)

538

539

```properties

540

# Enable/disable repository auto-configuration (default: true)

541

spring.data.jpa.repositories.enabled=true

542

543

# Repository bootstrap mode: default, deferred, lazy (default: default)

544

spring.data.jpa.repositories.bootstrap-mode=deferred

545

```

546

547

**Bootstrap Modes**:

548

- `default` - Repositories initialized eagerly at startup

549

- `deferred` - Repositories initialized when first accessed

550

- `lazy` - Repositories initialized on first actual use

551

552

### Entity Manager Factory Builder

553

554

Fluent builder for creating additional EntityManagerFactory instances with common configuration.

555

556

```java { .api }

557

package org.springframework.boot.orm.jpa;

558

559

public class EntityManagerFactoryBuilder {

560

/**

561

* Create a new EntityManagerFactoryBuilder instance.

562

*

563

* @param jpaVendorAdapter JPA vendor adapter

564

* @param jpaPropertiesFactory Factory function for creating JPA properties based on DataSource

565

* @param persistenceUnitManager Optional persistence unit manager (can be null)

566

* @since 3.4.4

567

*/

568

public EntityManagerFactoryBuilder(

569

JpaVendorAdapter jpaVendorAdapter,

570

Function<DataSource, Map<String, ?>> jpaPropertiesFactory,

571

PersistenceUnitManager persistenceUnitManager

572

) { }

573

574

/**

575

* Create a new EntityManagerFactoryBuilder instance with persistence unit root location.

576

*

577

* @param jpaVendorAdapter JPA vendor adapter

578

* @param jpaPropertiesFactory Factory function for creating JPA properties based on DataSource

579

* @param persistenceUnitManager Optional persistence unit manager (can be null)

580

* @param persistenceUnitRootLocation Persistence unit root location (can be null)

581

* @since 3.4.4

582

*/

583

public EntityManagerFactoryBuilder(

584

JpaVendorAdapter jpaVendorAdapter,

585

Function<DataSource, Map<String, ?>> jpaPropertiesFactory,

586

PersistenceUnitManager persistenceUnitManager,

587

URL persistenceUnitRootLocation

588

) { }

589

590

/**

591

* Create a new EntityManagerFactoryBuilder instance.

592

*

593

* @param jpaVendorAdapter JPA vendor adapter

594

* @param jpaProperties Static JPA properties map

595

* @param persistenceUnitManager Optional persistence unit manager (can be null)

596

* @deprecated since 3.4.4 for removal in 4.0.0 - Use constructor with Function parameter instead

597

*/

598

@Deprecated(since = "3.4.4", forRemoval = true)

599

public EntityManagerFactoryBuilder(

600

JpaVendorAdapter jpaVendorAdapter,

601

Map<String, ?> jpaProperties,

602

PersistenceUnitManager persistenceUnitManager

603

) { }

604

605

/**

606

* Create a new EntityManagerFactoryBuilder instance with persistence unit root location.

607

*

608

* @param jpaVendorAdapter JPA vendor adapter

609

* @param jpaProperties Static JPA properties map

610

* @param persistenceUnitManager Optional persistence unit manager (can be null)

611

* @param persistenceUnitRootLocation Persistence unit root location (can be null)

612

* @deprecated since 3.4.4 for removal in 4.0.0 - Use constructor with Function parameter instead

613

* @since 1.4.1

614

*/

615

@Deprecated(since = "3.4.4", forRemoval = true)

616

public EntityManagerFactoryBuilder(

617

JpaVendorAdapter jpaVendorAdapter,

618

Map<String, ?> jpaProperties,

619

PersistenceUnitManager persistenceUnitManager,

620

URL persistenceUnitRootLocation

621

) { }

622

623

/**

624

* Start building an EntityManagerFactory with a DataSource

625

*/

626

public Builder dataSource(DataSource dataSource) { }

627

628

/**

629

* Set async bootstrap executor for background initialization

630

*/

631

public void setBootstrapExecutor(AsyncTaskExecutor bootstrapExecutor) { }

632

633

/**

634

* Set persistence unit post processors

635

*/

636

public void setPersistenceUnitPostProcessors(

637

PersistenceUnitPostProcessor... postProcessors

638

) { }

639

640

/**

641

* Fluent builder for LocalContainerEntityManagerFactoryBean

642

*/

643

public static class Builder {

644

/**

645

* Set the managed types (entities) for this EntityManagerFactory

646

*/

647

public Builder managedTypes(PersistenceManagedTypes managedTypes) { }

648

649

/**

650

* Set packages to scan for entities

651

*/

652

public Builder packages(String... packagesToScan) { }

653

654

/**

655

* Set packages to scan using classes as package markers

656

*

657

* @param basePackageClasses Classes whose packages should be scanned

658

* @return Builder for fluent API

659

*/

660

public Builder packages(Class<?>... basePackageClasses) { }

661

662

/**

663

* Set persistence unit name

664

*/

665

public Builder persistenceUnit(String persistenceUnitName) { }

666

667

/**

668

* Set JPA properties

669

*/

670

public Builder properties(Map<String, ?> properties) { }

671

672

/**

673

* Set mapping resources (XML mappings)

674

*/

675

public Builder mappingResources(String... mappingResources) { }

676

677

/**

678

* Enable JTA transaction mode

679

*/

680

public Builder jta(boolean jta) { }

681

682

/**

683

* Build the LocalContainerEntityManagerFactoryBean

684

*/

685

public LocalContainerEntityManagerFactoryBean build() { }

686

}

687

}

688

```

689

690

**Usage Example - Multiple DataSources**:

691

692

```java

693

@Configuration

694

public class MultiDataSourceConfig {

695

696

@Bean

697

@Primary

698

@ConfigurationProperties(prefix = "spring.datasource.primary")

699

public DataSourceProperties primaryDataSourceProperties() {

700

return new DataSourceProperties();

701

}

702

703

@Bean

704

@Primary

705

public DataSource primaryDataSource() {

706

return primaryDataSourceProperties()

707

.initializeDataSourceBuilder()

708

.build();

709

}

710

711

@Bean

712

@Primary

713

public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(

714

EntityManagerFactoryBuilder builder,

715

@Qualifier("primaryDataSource") DataSource dataSource) {

716

return builder

717

.dataSource(dataSource)

718

.packages("com.example.primary.domain")

719

.persistenceUnit("primary")

720

.build();

721

}

722

723

@Bean

724

@ConfigurationProperties(prefix = "spring.datasource.secondary")

725

public DataSourceProperties secondaryDataSourceProperties() {

726

return new DataSourceProperties();

727

}

728

729

@Bean

730

public DataSource secondaryDataSource() {

731

return secondaryDataSourceProperties()

732

.initializeDataSourceBuilder()

733

.build();

734

}

735

736

@Bean

737

public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(

738

EntityManagerFactoryBuilder builder,

739

@Qualifier("secondaryDataSource") DataSource dataSource) {

740

return builder

741

.dataSource(dataSource)

742

.packages("com.example.secondary.domain")

743

.persistenceUnit("secondary")

744

.build();

745

}

746

}

747

```

748

749

### Customization Interfaces

750

751

Customize Hibernate and EntityManagerFactory configuration through callback interfaces.

752

753

#### HibernatePropertiesCustomizer

754

755

```java { .api }

756

package org.springframework.boot.autoconfigure.orm.jpa;

757

758

@FunctionalInterface

759

public interface HibernatePropertiesCustomizer {

760

/**

761

* Customize Hibernate properties before EntityManagerFactory creation.

762

*

763

* @param hibernateProperties Map of Hibernate properties to customize

764

*/

765

void customize(Map<String, Object> hibernateProperties);

766

}

767

```

768

769

**Usage Example**:

770

771

```java

772

@Configuration

773

public class HibernateConfig {

774

775

@Bean

776

public HibernatePropertiesCustomizer hibernatePropertiesCustomizer() {

777

return (hibernateProperties) -> {

778

// Enable Hibernate statistics

779

hibernateProperties.put("hibernate.generate_statistics", true);

780

781

// Configure second-level cache

782

hibernateProperties.put("hibernate.cache.use_second_level_cache", true);

783

hibernateProperties.put("hibernate.cache.region.factory_class",

784

"org.hibernate.cache.jcache.JCacheRegionFactory");

785

786

// Configure batch processing

787

hibernateProperties.put("hibernate.jdbc.batch_size", 25);

788

hibernateProperties.put("hibernate.order_inserts", true);

789

hibernateProperties.put("hibernate.order_updates", true);

790

};

791

}

792

}

793

```

794

795

#### EntityManagerFactoryBuilderCustomizer

796

797

```java { .api }

798

package org.springframework.boot.autoconfigure.orm.jpa;

799

800

@FunctionalInterface

801

public interface EntityManagerFactoryBuilderCustomizer {

802

/**

803

* Customize the EntityManagerFactoryBuilder before it's used.

804

*

805

* @param builder The EntityManagerFactoryBuilder to customize

806

*/

807

void customize(EntityManagerFactoryBuilder builder);

808

}

809

```

810

811

**Usage Example**:

812

813

```java

814

@Configuration

815

public class JpaConfig {

816

817

@Bean

818

public EntityManagerFactoryBuilderCustomizer entityManagerFactoryBuilderCustomizer() {

819

return (builder) -> {

820

// Configure async bootstrap for faster startup

821

builder.setBootstrapExecutor(asyncTaskExecutor());

822

823

// Add custom persistence unit post processors

824

builder.setPersistenceUnitPostProcessors(

825

new CustomPersistenceUnitPostProcessor()

826

);

827

};

828

}

829

830

@Bean

831

public AsyncTaskExecutor asyncTaskExecutor() {

832

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

833

executor.setCorePoolSize(2);

834

executor.setMaxPoolSize(2);

835

executor.setThreadNamePrefix("jpa-bootstrap-");

836

executor.initialize();

837

return executor;

838

}

839

}

840

```

841

842

### Initialization Order Control

843

844

Control EntityManagerFactory initialization order relative to other beans.

845

846

```java { .api }

847

package org.springframework.boot.autoconfigure.orm.jpa;

848

849

public class EntityManagerFactoryDependsOnPostProcessor

850

extends AbstractDependsOnBeanFactoryPostProcessor {

851

852

/**

853

* Make EntityManagerFactory depend on specific bean names.

854

*

855

* @param dependsOn Bean names that EntityManagerFactory should depend on

856

*/

857

public EntityManagerFactoryDependsOnPostProcessor(String... dependsOn) { }

858

859

/**

860

* Make EntityManagerFactory depend on beans of specific types.

861

*

862

* @param dependsOn Bean types that EntityManagerFactory should depend on

863

*/

864

public EntityManagerFactoryDependsOnPostProcessor(Class<?>... dependsOn) { }

865

}

866

```

867

868

**Usage Example**:

869

870

```java

871

@Configuration

872

public class InitializationOrderConfig {

873

874

/**

875

* Ensure EntityManagerFactory initializes after Flyway migrations

876

*/

877

@Bean

878

public static EntityManagerFactoryDependsOnPostProcessor

879

entityManagerFactoryDependsOnPostProcessor() {

880

return new EntityManagerFactoryDependsOnPostProcessor(Flyway.class);

881

}

882

}

883

```

884

885

### Naming Strategies

886

887

Customize how entity and column names are mapped to database table and column names.

888

889

```java { .api }

890

package org.springframework.boot.orm.jpa.hibernate;

891

892

import org.hibernate.boot.model.naming.Identifier;

893

import org.hibernate.boot.model.naming.ImplicitJoinTableNameSource;

894

import org.hibernate.boot.model.naming.ImplicitNamingStrategy;

895

import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;

896

897

/**

898

* Spring's default implicit naming strategy.

899

* Join tables use format: {owning_table}_{property_name}

900

* Identical to ImplicitNamingStrategyJpaCompliantImpl except for join table naming.

901

*/

902

public class SpringImplicitNamingStrategy

903

extends ImplicitNamingStrategyJpaCompliantImpl {

904

905

/**

906

* Determine the implicit name for a join table.

907

* Uses format: {owning_physical_table_name}_{association_owning_property_name}

908

*

909

* @param source The source metadata for the join table

910

* @return The identifier for the join table name

911

*/

912

@Override

913

public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) { }

914

}

915

```

916

917

**Providing Custom Naming Strategy**:

918

919

```java

920

@Configuration

921

public class NamingStrategyConfig {

922

923

/**

924

* Override the default physical naming strategy

925

*/

926

@Bean

927

public PhysicalNamingStrategy physicalNamingStrategy() {

928

// Use standard JPA naming (no snake_case conversion)

929

return new PhysicalNamingStrategyStandardImpl();

930

}

931

932

/**

933

* Override the default implicit naming strategy

934

*/

935

@Bean

936

public ImplicitNamingStrategy implicitNamingStrategy() {

937

return new SpringImplicitNamingStrategy();

938

}

939

}

940

```

941

942

Or via properties:

943

944

```properties

945

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

946

spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

947

```

948

949

### Entity Scanning

950

951

Control which packages are scanned for JPA entities.

952

953

**Default Behavior**: Auto-scans main application package and sub-packages.

954

955

**Custom Scanning**:

956

957

```java

958

@Configuration

959

@EntityScan(basePackages = {

960

"com.example.domain",

961

"com.example.shared.entities"

962

})

963

public class EntityScanConfig {

964

}

965

```

966

967

**Entity Configuration**:

968

969

```java

970

@Entity

971

@Table(name = "products", indexes = {

972

@Index(name = "idx_product_sku", columnList = "sku"),

973

@Index(name = "idx_product_category", columnList = "category_id")

974

})

975

public class Product {

976

977

@Id

978

@GeneratedValue(strategy = GenerationType.IDENTITY)

979

private Long id;

980

981

@Column(unique = true, nullable = false, length = 50)

982

private String sku;

983

984

@Column(nullable = false)

985

private String name;

986

987

@Column(precision = 10, scale = 2)

988

private BigDecimal price;

989

990

@ManyToOne(fetch = FetchType.LAZY)

991

@JoinColumn(name = "category_id")

992

private Category category;

993

994

@OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)

995

private List<Review> reviews = new ArrayList<>();

996

997

// Getters and setters

998

}

999

```

1000

1001

### Spring Data JPA Repositories

1002

1003

Create repository interfaces that Spring Data JPA automatically implements.

1004

1005

**Repository Interfaces**:

1006

1007

```java { .api }

1008

// CrudRepository - Basic CRUD operations

1009

public interface CrudRepository<T, ID> extends Repository<T, ID> {

1010

<S extends T> S save(S entity);

1011

<S extends T> Iterable<S> saveAll(Iterable<S> entities);

1012

Optional<T> findById(ID id);

1013

boolean existsById(ID id);

1014

Iterable<T> findAll();

1015

Iterable<T> findAllById(Iterable<ID> ids);

1016

long count();

1017

void deleteById(ID id);

1018

void delete(T entity);

1019

void deleteAllById(Iterable<? extends ID> ids);

1020

void deleteAll(Iterable<? extends T> entities);

1021

void deleteAll();

1022

}

1023

1024

// JpaRepository - Adds JPA-specific methods

1025

public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID> {

1026

List<T> findAll();

1027

List<T> findAll(Sort sort);

1028

List<T> findAllById(Iterable<ID> ids);

1029

<S extends T> List<S> saveAll(Iterable<S> entities);

1030

void flush();

1031

<S extends T> S saveAndFlush(S entity);

1032

<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

1033

void deleteInBatch(Iterable<T> entities);

1034

void deleteAllInBatch(Iterable<T> entities);

1035

void deleteAllByIdInBatch(Iterable<ID> ids);

1036

void deleteAllInBatch();

1037

T getOne(ID id); // Deprecated, use getReferenceById

1038

T getReferenceById(ID id);

1039

}

1040

1041

// PagingAndSortingRepository - Pagination and sorting support

1042

public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {

1043

Iterable<T> findAll(Sort sort);

1044

Page<T> findAll(Pageable pageable);

1045

}

1046

```

1047

1048

**Query Methods**: Spring Data JPA derives queries from method names.

1049

1050

```java

1051

public interface UserRepository extends JpaRepository<User, Long> {

1052

// Derived query methods

1053

List<User> findByName(String name);

1054

List<User> findByNameAndEmail(String name, String email);

1055

List<User> findByNameOrEmail(String name, String email);

1056

List<User> findByAgeBetween(int minAge, int maxAge);

1057

List<User> findByNameContaining(String namePart);

1058

List<User> findByNameStartingWith(String prefix);

1059

List<User> findByNameIgnoreCase(String name);

1060

List<User> findByOrderByNameAsc();

1061

Optional<User> findFirstByEmail(String email);

1062

1063

// With pagination and sorting

1064

Page<User> findByName(String name, Pageable pageable);

1065

List<User> findByAge(int age, Sort sort);

1066

1067

// Count and exists queries

1068

long countByAge(int age);

1069

boolean existsByEmail(String email);

1070

1071

// Delete queries

1072

long deleteByAge(int age);

1073

void removeByName(String name);

1074

1075

// Custom JPQL queries

1076

@Query("SELECT u FROM User u WHERE u.age > :age")

1077

List<User> findUsersOlderThan(@Param("age") int age);

1078

1079

@Query("SELECT u FROM User u WHERE u.name LIKE %:namePart%")

1080

List<User> searchByName(@Param("namePart") String namePart);

1081

1082

// Native SQL queries

1083

@Query(value = "SELECT * FROM users WHERE email = ?1", nativeQuery = true)

1084

User findByEmailNative(String email);

1085

1086

// Modifying queries

1087

@Modifying

1088

@Query("UPDATE User u SET u.active = :active WHERE u.id = :id")

1089

int updateActiveStatus(@Param("id") Long id, @Param("active") boolean active);

1090

}

1091

```

1092

1093

**Pagination Example**:

1094

1095

```java

1096

@Service

1097

public class UserService {

1098

private final UserRepository userRepository;

1099

1100

public UserService(UserRepository userRepository) {

1101

this.userRepository = userRepository;

1102

}

1103

1104

public Page<User> getUsers(int page, int size) {

1105

Pageable pageable = PageRequest.of(page, size, Sort.by("name").ascending());

1106

return userRepository.findAll(pageable);

1107

}

1108

1109

public Page<User> searchUsers(String name, int page, int size) {

1110

Pageable pageable = PageRequest.of(page, size);

1111

return userRepository.findByName(name, pageable);

1112

}

1113

}

1114

```

1115

1116

### Transaction Management

1117

1118

JPA transactions are managed automatically through Spring's `@Transactional` annotation.

1119

1120

**Transaction Configuration**:

1121

1122

```java

1123

@Service

1124

public class OrderService {

1125

private final OrderRepository orderRepository;

1126

private final InventoryService inventoryService;

1127

1128

public OrderService(OrderRepository orderRepository,

1129

InventoryService inventoryService) {

1130

this.orderRepository = orderRepository;

1131

this.inventoryService = inventoryService;

1132

}

1133

1134

/**

1135

* Transactional method - changes committed or rolled back together

1136

*/

1137

@Transactional

1138

public Order createOrder(OrderRequest request) {

1139

// Check inventory

1140

inventoryService.reserveItems(request.getItems());

1141

1142

// Create order

1143

Order order = new Order();

1144

order.setCustomerId(request.getCustomerId());

1145

order.setItems(request.getItems());

1146

order.setStatus(OrderStatus.PENDING);

1147

1148

return orderRepository.save(order);

1149

// Transaction commits here if no exception thrown

1150

}

1151

1152

/**

1153

* Read-only transaction (optimization)

1154

*/

1155

@Transactional(readOnly = true)

1156

public Order getOrder(Long orderId) {

1157

return orderRepository.findById(orderId)

1158

.orElseThrow(() -> new OrderNotFoundException(orderId));

1159

}

1160

1161

/**

1162

* Custom transaction configuration

1163

*/

1164

@Transactional(

1165

propagation = Propagation.REQUIRES_NEW,

1166

isolation = Isolation.SERIALIZABLE,

1167

timeout = 30,

1168

rollbackFor = BusinessException.class

1169

)

1170

public void processRefund(Long orderId) {

1171

// Process refund in new transaction

1172

}

1173

}

1174

```

1175

1176

### JTA Integration

1177

1178

JTA platform automatically configured when JTA transaction manager is detected.

1179

1180

```java { .api }

1181

package org.springframework.boot.orm.jpa.hibernate;

1182

1183

import jakarta.transaction.TransactionManager;

1184

import jakarta.transaction.UserTransaction;

1185

import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;

1186

import org.springframework.transaction.jta.JtaTransactionManager;

1187

1188

/**

1189

* Hibernate JTA platform that integrates with Spring's JtaTransactionManager.

1190

* Automatically configured when JTA is detected.

1191

*/

1192

public class SpringJtaPlatform extends AbstractJtaPlatform {

1193

/**

1194

* Create JTA platform with Spring's transaction manager.

1195

*

1196

* @param transactionManager The JTA transaction manager

1197

*/

1198

public SpringJtaPlatform(JtaTransactionManager transactionManager) { }

1199

1200

/**

1201

* Locate the TransactionManager from the Spring JtaTransactionManager.

1202

*

1203

* @return The JTA TransactionManager

1204

*/

1205

@Override

1206

protected TransactionManager locateTransactionManager() { }

1207

1208

/**

1209

* Locate the UserTransaction from the Spring JtaTransactionManager.

1210

*

1211

* @return The JTA UserTransaction

1212

*/

1213

@Override

1214

protected UserTransaction locateUserTransaction() { }

1215

}

1216

```

1217

1218

## Types

1219

1220

```java { .api }

1221

// Database enum for spring.jpa.database property

1222

// Package: org.springframework.orm.jpa.vendor (Spring Framework)

1223

public enum Database {

1224

DEFAULT,

1225

DB2,

1226

DERBY,

1227

H2,

1228

HANA,

1229

HSQL,

1230

INFORMIX,

1231

MYSQL,

1232

ORACLE,

1233

POSTGRESQL,

1234

SQL_SERVER,

1235

SYBASE

1236

}

1237

1238

// Bootstrap mode for repository initialization

1239

// Package: org.springframework.data.repository.config (Spring Data Commons)

1240

public enum BootstrapMode {

1241

DEFAULT, // Eager initialization at startup

1242

DEFERRED, // Initialize when first accessed

1243

LAZY // Initialize on first actual use

1244

}

1245

1246

// Hibernate settings container (internal use)

1247

public class HibernateSettings {

1248

/**

1249

* Set the DDL auto supplier and return this instance for method chaining.

1250

*

1251

* @param ddlAuto Supplier for DDL auto mode

1252

* @return This HibernateSettings instance

1253

*/

1254

public HibernateSettings ddlAuto(Supplier<String> ddlAuto) { }

1255

1256

/**

1257

* Get the DDL auto mode.

1258

*

1259

* @return DDL auto mode or null if not set

1260

*/

1261

public String getDdlAuto() { }

1262

1263

/**

1264

* Set the Hibernate properties customizers and return this instance for method chaining.

1265

*

1266

* @param customizers Collection of customizers to apply

1267

* @return This HibernateSettings instance

1268

*/

1269

public HibernateSettings hibernatePropertiesCustomizers(

1270

Collection<HibernatePropertiesCustomizer> customizers

1271

) { }

1272

1273

/**

1274

* Get the Hibernate properties customizers.

1275

*

1276

* @return Collection of customizers

1277

*/

1278

public Collection<HibernatePropertiesCustomizer> getHibernatePropertiesCustomizers() { }

1279

}

1280

```

1281

1282

## Dependencies

1283

1284

This starter aggregates the following dependencies:

1285

1286

- `spring-boot-starter` - Core Spring Boot functionality

1287

- `spring-boot-starter-jdbc` - JDBC and DataSource support

1288

- `hibernate-core` (org.hibernate.orm) - Hibernate ORM implementation

1289

- `spring-data-jpa` (org.springframework.data) - Spring Data JPA repositories

1290

- `spring-aspects` (org.springframework) - AOP support for @Transactional

1291

1292

## Common Patterns

1293

1294

### Testing with @DataJpaTest

1295

1296

```java

1297

@DataJpaTest

1298

class UserRepositoryTest {

1299

1300

@Autowired

1301

private UserRepository userRepository;

1302

1303

@Autowired

1304

private TestEntityManager entityManager;

1305

1306

@Test

1307

void testFindByName() {

1308

// Given

1309

User user = new User();

1310

user.setName("Alice");

1311

user.setEmail("alice@example.com");

1312

entityManager.persist(user);

1313

entityManager.flush();

1314

1315

// When

1316

List<User> users = userRepository.findByName("Alice");

1317

1318

// Then

1319

assertThat(users).hasSize(1);

1320

assertThat(users.get(0).getEmail()).isEqualTo("alice@example.com");

1321

}

1322

}

1323

```

1324

1325

### Auditing

1326

1327

Enable automatic auditing of created/modified dates and users:

1328

1329

```java

1330

@Configuration

1331

@EnableJpaAuditing

1332

public class JpaAuditingConfig {

1333

1334

@Bean

1335

public AuditorAware<String> auditorProvider() {

1336

// Return current user from security context

1337

return () -> Optional.of(

1338

SecurityContextHolder.getContext()

1339

.getAuthentication()

1340

.getName()

1341

);

1342

}

1343

}

1344

1345

@Entity

1346

@EntityListeners(AuditingEntityListener.class)

1347

public class AuditableEntity {

1348

1349

@CreatedDate

1350

@Column(nullable = false, updatable = false)

1351

private Instant createdDate;

1352

1353

@LastModifiedDate

1354

private Instant lastModifiedDate;

1355

1356

@CreatedBy

1357

@Column(nullable = false, updatable = false)

1358

private String createdBy;

1359

1360

@LastModifiedBy

1361

private String lastModifiedBy;

1362

}

1363

```

1364

1365

### Specifications (Dynamic Queries)

1366

1367

```java

1368

public interface UserRepository extends JpaRepository<User, Long>,

1369

JpaSpecificationExecutor<User> {

1370

}

1371

1372

public class UserSpecifications {

1373

1374

public static Specification<User> hasName(String name) {

1375

return (root, query, cb) ->

1376

name == null ? null : cb.equal(root.get("name"), name);

1377

}

1378

1379

public static Specification<User> isActive() {

1380

return (root, query, cb) -> cb.isTrue(root.get("active"));

1381

}

1382

1383

public static Specification<User> ageGreaterThan(int age) {

1384

return (root, query, cb) -> cb.greaterThan(root.get("age"), age);

1385

}

1386

}

1387

1388

// Usage

1389

@Service

1390

public class UserSearchService {

1391

private final UserRepository userRepository;

1392

1393

public List<User> searchUsers(String name, Integer minAge, Boolean active) {

1394

Specification<User> spec = Specification.where(null);

1395

1396

if (name != null) {

1397

spec = spec.and(UserSpecifications.hasName(name));

1398

}

1399

if (minAge != null) {

1400

spec = spec.and(UserSpecifications.ageGreaterThan(minAge));

1401

}

1402

if (Boolean.TRUE.equals(active)) {

1403

spec = spec.and(UserSpecifications.isActive());

1404

}

1405

1406

return userRepository.findAll(spec);

1407

}

1408

}

1409

```

1410