or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

exception-handling.mdhibernate-integration.mdindex.mdjpa-integration.mdpersistence-context.mdtransaction-management.md

persistence-context.mddocs/

0

# Persistence Context Management

1

2

Spring ORM provides advanced persistence context management through annotation-driven dependency injection, container-managed and application-managed persistence contexts, persistence unit configuration, and comprehensive lifecycle management. This enables proper resource management and integration with Spring's dependency injection container.

3

4

## Capabilities

5

6

### Persistence Annotation Processing

7

8

Automatic processing of JPA annotations for dependency injection of EntityManager and EntityManagerFactory instances with proper lifecycle management.

9

10

```java { .api }

11

public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor,

12

DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware, Serializable {

13

public void setDefaultPersistenceUnitName(String unitName);

14

public void setPersistenceUnits(Map<String, PersistenceUnitInfo> persistenceUnits);

15

public void setPersistenceContexts(Map<String, EntityManagerFactory> persistenceContexts);

16

public void setJndiEnvironment(Properties jndiEnvironment);

17

public void setResourceRef(boolean resourceRef);

18

19

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException;

20

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

21

public Object postProcessBeforeInstantiation(Class<?> beanType, String beanName) throws BeansException;

22

public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

23

public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

24

}

25

26

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})

27

@Retention(RetentionPolicy.RUNTIME)

28

public @interface PersistenceContext {

29

String name() default "";

30

String unitName() default "";

31

PersistenceContextType type() default PersistenceContextType.TRANSACTION;

32

SynchronizationType synchronization() default SynchronizationType.SYNCHRONIZED;

33

PersistenceProperty[] properties() default {};

34

}

35

36

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})

37

@Retention(RetentionPolicy.RUNTIME)

38

public @interface PersistenceUnit {

39

String name() default "";

40

String unitName() default "";

41

}

42

43

public enum PersistenceContextType {

44

TRANSACTION,

45

EXTENDED

46

}

47

48

public enum SynchronizationType {

49

SYNCHRONIZED,

50

UNSYNCHRONIZED

51

}

52

```

53

54

#### Usage Example

55

56

```java

57

@Configuration

58

@EnableJpaRepositories

59

public class PersistenceConfig {

60

61

@Bean

62

public PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {

63

PersistenceAnnotationBeanPostProcessor processor = new PersistenceAnnotationBeanPostProcessor();

64

65

// Set default persistence unit name

66

processor.setDefaultPersistenceUnitName("primaryPU");

67

68

// Configure specific persistence units

69

Map<String, PersistenceUnitInfo> persistenceUnits = new HashMap<>();

70

persistenceUnits.put("primaryPU", primaryPersistenceUnitInfo());

71

persistenceUnits.put("secondaryPU", secondaryPersistenceUnitInfo());

72

processor.setPersistenceUnits(persistenceUnits);

73

74

// Configure EntityManagerFactory mappings

75

Map<String, EntityManagerFactory> persistenceContexts = new HashMap<>();

76

persistenceContexts.put("primaryPU", primaryEntityManagerFactory());

77

persistenceContexts.put("secondaryPU", secondaryEntityManagerFactory());

78

processor.setPersistenceContexts(persistenceContexts);

79

80

return processor;

81

}

82

}

83

84

@Repository

85

public class UserRepository {

86

87

// Inject default EntityManager

88

@PersistenceContext

89

private EntityManager entityManager;

90

91

// Inject EntityManager for specific persistence unit

92

@PersistenceContext(unitName = "primaryPU")

93

private EntityManager primaryEntityManager;

94

95

// Inject EntityManager with extended persistence context

96

@PersistenceContext(

97

unitName = "primaryPU",

98

type = PersistenceContextType.EXTENDED,

99

properties = {

100

@PersistenceProperty(name = "hibernate.cache.use_second_level_cache", value = "true"),

101

@PersistenceProperty(name = "hibernate.cache.region.factory_class",

102

value = "org.hibernate.cache.jcache.JCacheRegionFactory")

103

}

104

)

105

private EntityManager extendedEntityManager;

106

107

// Inject EntityManagerFactory

108

@PersistenceUnit(unitName = "primaryPU")

109

private EntityManagerFactory entityManagerFactory;

110

111

@Transactional

112

public void saveUser(User user) {

113

entityManager.persist(user);

114

}

115

116

@Transactional(readOnly = true)

117

public User findUserById(Long id) {

118

return entityManager.find(User.class, id);

119

}

120

121

// Using EntityManagerFactory for programmatic EntityManager creation

122

public void performBatchOperation(List<User> users) {

123

EntityManager em = entityManagerFactory.createEntityManager();

124

EntityTransaction tx = em.getTransaction();

125

126

try {

127

tx.begin();

128

129

for (int i = 0; i < users.size(); i++) {

130

em.persist(users.get(i));

131

132

if (i % 50 == 0) {

133

em.flush();

134

em.clear();

135

}

136

}

137

138

tx.commit();

139

} catch (Exception ex) {

140

if (tx.isActive()) {

141

tx.rollback();

142

}

143

throw ex;

144

} finally {

145

em.close();

146

}

147

}

148

}

149

```

150

151

### Persistence Unit Management

152

153

Comprehensive management of JPA persistence units including configuration, managed types discovery, and persistence.xml processing.

154

155

```java { .api }

156

public interface PersistenceUnitManager {

157

PersistenceUnitInfo obtainDefaultPersistenceUnitInfo() throws IllegalArgumentException;

158

PersistenceUnitInfo obtainPersistenceUnitInfo(String persistenceUnitName) throws IllegalArgumentException, IllegalStateException;

159

}

160

161

public class DefaultPersistenceUnitManager implements PersistenceUnitManager, ResourceLoaderAware, DisposableBean {

162

public static final String DEFAULT_PERSISTENCE_XML_LOCATION = "classpath*:META-INF/persistence.xml";

163

public static final String ORIGINAL_DEFAULT_PERSISTENCE_UNIT_ROOT_LOCATION = "classpath:";

164

public static final String ORIGINAL_DEFAULT_PERSISTENCE_UNIT_NAME = "default";

165

166

public void setPersistenceXmlLocations(String... persistenceXmlLocations);

167

public void setDefaultPersistenceUnitRootLocation(String defaultPersistenceUnitRootLocation);

168

public void setDefaultPersistenceUnitName(String defaultPersistenceUnitName);

169

public void setPackagesToScan(String... packagesToScan);

170

public void setManagedTypes(PersistenceManagedTypes managedTypes);

171

public void setManagedClassNameFilter(ManagedClassNameFilter managedClassNameFilter);

172

public void setMappingResources(String... mappingResources);

173

public void setJtaDataSource(DataSource jtaDataSource);

174

public void setDataSource(DataSource dataSource);

175

public void setPersistenceUnitPostProcessors(PersistenceUnitPostProcessor... persistenceUnitPostProcessors);

176

public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver);

177

178

public PersistenceUnitInfo obtainDefaultPersistenceUnitInfo() throws IllegalArgumentException;

179

public PersistenceUnitInfo obtainPersistenceUnitInfo(String persistenceUnitName) throws IllegalArgumentException, IllegalStateException;

180

}

181

182

public interface PersistenceUnitPostProcessor {

183

void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui);

184

}

185

186

public interface ManagedClassNameFilter {

187

boolean matches(String className);

188

}

189

```

190

191

#### Usage Example

192

193

```java

194

@Configuration

195

public class PersistenceUnitConfig {

196

197

@Bean

198

public PersistenceUnitManager persistenceUnitManager() {

199

DefaultPersistenceUnitManager manager = new DefaultPersistenceUnitManager();

200

201

// Set persistence.xml locations

202

manager.setPersistenceXmlLocations(

203

"classpath:META-INF/persistence.xml",

204

"classpath:META-INF/test-persistence.xml"

205

);

206

207

// Configure default settings

208

manager.setDefaultPersistenceUnitRootLocation("classpath:");

209

manager.setDefaultPersistenceUnitName("primaryPU");

210

211

// Set packages to scan for entities

212

manager.setPackagesToScan(

213

"com.example.entity",

214

"com.example.model",

215

"com.example.domain"

216

);

217

218

// Configure managed types filter

219

manager.setManagedClassNameFilter(className ->

220

className.startsWith("com.example") &&

221

!className.contains("Test")

222

);

223

224

// Set mapping resources

225

manager.setMappingResources(

226

"META-INF/orm.xml",

227

"META-INF/queries.xml"

228

);

229

230

// Configure data sources

231

manager.setDataSource(primaryDataSource());

232

manager.setJtaDataSource(jtaDataSource());

233

234

// Add post-processors

235

manager.setPersistenceUnitPostProcessors(

236

new CustomPersistenceUnitPostProcessor(),

237

new AuditingPersistenceUnitPostProcessor()

238

);

239

240

return manager;

241

}

242

243

@Bean

244

public DataSource primaryDataSource() {

245

HikariDataSource dataSource = new HikariDataSource();

246

dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/primary");

247

dataSource.setUsername("user");

248

dataSource.setPassword("password");

249

return dataSource;

250

}

251

}

252

253

// Custom post-processor for persistence unit customization

254

public class CustomPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor {

255

256

@Override

257

public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {

258

// Add custom properties

259

pui.getProperties().setProperty("hibernate.show_sql", "true");

260

pui.getProperties().setProperty("hibernate.format_sql", "true");

261

pui.getProperties().setProperty("hibernate.use_sql_comments", "true");

262

263

// Add additional managed classes programmatically

264

pui.addManagedClassName("com.example.entity.DynamicEntity");

265

266

// Add mapping files

267

pui.addMappingFileName("META-INF/custom-mappings.xml");

268

269

// Customize transaction type based on environment

270

if (isProductionEnvironment()) {

271

pui.setTransactionType(PersistenceUnitTransactionType.JTA);

272

} else {

273

pui.setTransactionType(PersistenceUnitTransactionType.RESOURCE_LOCAL);

274

}

275

}

276

}

277

```

278

279

### Managed Types Discovery

280

281

Support for discovering and configuring managed entity types, embeddables, and mapped superclasses for JPA persistence units.

282

283

```java { .api }

284

public interface PersistenceManagedTypes {

285

Set<String> getManagedClassNames();

286

Set<String> getManagedPackages();

287

288

static PersistenceManagedTypes of(String... managedClassNames);

289

static PersistenceManagedTypes of(Class<?>... managedClasses);

290

static PersistenceManagedTypes empty();

291

static PersistenceManagedTypes fromIterable(Iterable<String> managedClassNames);

292

}

293

294

public class SimplePersistenceManagedTypes implements PersistenceManagedTypes {

295

public SimplePersistenceManagedTypes(Collection<String> managedClassNames, Collection<String> managedPackages);

296

297

public Set<String> getManagedClassNames();

298

public Set<String> getManagedPackages();

299

}

300

301

public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {

302

public void setPersistenceUnitName(String persistenceUnitName);

303

public void setPersistenceProviderClassName(String persistenceProviderClassName);

304

public void setTransactionType(PersistenceUnitTransactionType transactionType);

305

public void setJtaDataSource(DataSource jtaDataSource);

306

public void setNonJtaDataSource(DataSource nonJtaDataSource);

307

public void addManagedClassName(String managedClassName);

308

public void addMappingFileName(String mappingFileName);

309

public void addJarFileUrl(URL jarFileUrl);

310

public void setPersistenceUnitRootUrl(URL persistenceUnitRootUrl);

311

public void setExcludeUnlistedClasses(boolean excludeUnlistedClasses);

312

public void setSharedCacheMode(SharedCacheMode sharedCacheMode);

313

public void setValidationMode(ValidationMode validationMode);

314

public void addProperty(String name, Object value);

315

public void setProperties(Properties properties);

316

public void setClassLoader(ClassLoader classLoader);

317

}

318

```

319

320

#### Usage Example

321

322

```java

323

@Configuration

324

public class ManagedTypesConfig {

325

326

@Bean

327

public PersistenceManagedTypes primaryManagedTypes() {

328

// Static managed types

329

return PersistenceManagedTypes.of(

330

User.class,

331

Product.class,

332

Order.class,

333

OrderItem.class,

334

Customer.class

335

);

336

}

337

338

@Bean

339

public PersistenceManagedTypes dynamicManagedTypes() {

340

// Dynamic managed types discovery

341

Set<String> managedClassNames = new HashSet<>();

342

Set<String> managedPackages = new HashSet<>();

343

344

// Scan packages for entities

345

scanPackageForEntities("com.example.entity", managedClassNames);

346

scanPackageForEntities("com.example.model", managedClassNames);

347

348

// Add packages for automatic scanning

349

managedPackages.add("com.example.embeddable");

350

managedPackages.add("com.example.converter");

351

352

return new SimplePersistenceManagedTypes(managedClassNames, managedPackages);

353

}

354

355

@Bean

356

public LocalContainerEntityManagerFactoryBean entityManagerFactory(

357

PersistenceManagedTypes managedTypes) {

358

LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();

359

em.setDataSource(dataSource());

360

em.setManagedTypes(managedTypes);

361

em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());

362

return em;

363

}

364

365

private void scanPackageForEntities(String packageName, Set<String> managedClassNames) {

366

// Implementation would use reflection or classpath scanning

367

// to discover @Entity, @Embeddable, @MappedSuperclass annotations

368

ClassPathScanningCandidateComponentProvider scanner =

369

new ClassPathScanningCandidateComponentProvider(false);

370

371

scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));

372

scanner.addIncludeFilter(new AnnotationTypeFilter(Embeddable.class));

373

scanner.addIncludeFilter(new AnnotationTypeFilter(MappedSuperclass.class));

374

375

for (BeanDefinition bd : scanner.findCandidateComponents(packageName)) {

376

managedClassNames.add(bd.getBeanClassName());

377

}

378

}

379

}

380

381

// Custom managed types implementation with filtering

382

public class FilteredPersistenceManagedTypes implements PersistenceManagedTypes {

383

384

private final Set<String> managedClassNames;

385

private final Set<String> managedPackages;

386

private final Predicate<String> classFilter;

387

388

public FilteredPersistenceManagedTypes(

389

Set<String> managedClassNames,

390

Set<String> managedPackages,

391

Predicate<String> classFilter) {

392

this.managedClassNames = managedClassNames;

393

this.managedPackages = managedPackages;

394

this.classFilter = classFilter;

395

}

396

397

@Override

398

public Set<String> getManagedClassNames() {

399

return managedClassNames.stream()

400

.filter(classFilter)

401

.collect(Collectors.toSet());

402

}

403

404

@Override

405

public Set<String> getManagedPackages() {

406

return managedPackages;

407

}

408

}

409

```

410

411

### Extended EntityManager Support

412

413

Support for creating extended EntityManager instances that span multiple transactions and provide application-managed persistence contexts.

414

415

```java { .api }

416

public abstract class ExtendedEntityManagerCreator {

417

public static EntityManager createApplicationManagedEntityManager(EntityManager rawEntityManager, EntityManagerFactoryInfo emfInfo);

418

public static EntityManager createContainerManagedEntityManager(EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction);

419

}

420

421

public class SharedEntityManagerBean extends EntityManagerFactoryAccessor

422

implements FactoryBean<EntityManager>, InitializingBean {

423

public void setPersistenceUnitName(String persistenceUnitName);

424

public void setJpaProperties(Properties jpaProperties);

425

public void setEntityManagerInterface(Class<? extends EntityManager> entityManagerInterface);

426

public void setSynchronizedWithTransaction(boolean synchronizedWithTransaction);

427

428

public EntityManager getObject();

429

public Class<? extends EntityManager> getObjectType();

430

public boolean isSingleton();

431

}

432

433

public interface EntityManagerProxy extends EntityManager {

434

EntityManager getTargetEntityManager();

435

}

436

```

437

438

#### Usage Example

439

440

```java

441

@Configuration

442

public class ExtendedEntityManagerConfig {

443

444

@Bean

445

public EntityManager applicationManagedEntityManager(

446

EntityManagerFactory entityManagerFactory) {

447

// Create application-managed EntityManager

448

EntityManager rawEntityManager = entityManagerFactory.createEntityManager();

449

EntityManagerFactoryInfo emfInfo = (EntityManagerFactoryInfo) entityManagerFactory;

450

451

return ExtendedEntityManagerCreator.createApplicationManagedEntityManager(

452

rawEntityManager,

453

emfInfo

454

);

455

}

456

457

@Bean

458

public EntityManager containerManagedEntityManager(

459

EntityManagerFactory entityManagerFactory) {

460

// Create container-managed EntityManager with custom properties

461

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

462

properties.put("hibernate.jdbc.fetch_size", 50);

463

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

464

465

return ExtendedEntityManagerCreator.createContainerManagedEntityManager(

466

entityManagerFactory,

467

properties,

468

true // synchronized with transaction

469

);

470

}

471

472

@Bean

473

public SharedEntityManagerBean sharedEntityManager() {

474

SharedEntityManagerBean bean = new SharedEntityManagerBean();

475

bean.setPersistenceUnitName("primaryPU");

476

477

// Custom JPA properties

478

Properties jpaProperties = new Properties();

479

jpaProperties.setProperty("hibernate.cache.use_query_cache", "true");

480

jpaProperties.setProperty("hibernate.cache.use_second_level_cache", "true");

481

bean.setJpaProperties(jpaProperties);

482

483

// Specify EntityManager interface (for proxy creation)

484

bean.setEntityManagerInterface(EntityManager.class);

485

486

// Configure transaction synchronization

487

bean.setSynchronizedWithTransaction(false);

488

489

return bean;

490

}

491

}

492

493

@Service

494

public class ExtendedPersistenceService {

495

496

// Application-managed EntityManager (spans multiple transactions)

497

@Autowired

498

@Qualifier("applicationManagedEntityManager")

499

private EntityManager applicationEntityManager;

500

501

// Container-managed EntityManager (transaction-scoped)

502

@Autowired

503

@Qualifier("containerManagedEntityManager")

504

private EntityManager containerEntityManager;

505

506

// Shared EntityManager (thread-safe proxy)

507

@Autowired

508

@Qualifier("sharedEntityManager")

509

private EntityManager sharedEntityManager;

510

511

// Extended persistence context for complex operations

512

public void performExtendedOperation(List<Long> userIds) {

513

try {

514

applicationEntityManager.getTransaction().begin();

515

516

// Load entities in extended context

517

List<User> users = new ArrayList<>();

518

for (Long id : userIds) {

519

User user = applicationEntityManager.find(User.class, id);

520

if (user != null) {

521

users.add(user);

522

}

523

}

524

525

// Perform complex modifications

526

for (User user : users) {

527

// Entities remain managed across method calls

528

processUser(user);

529

updateUserProfile(user);

530

addUserActivity(user);

531

}

532

533

applicationEntityManager.getTransaction().commit();

534

535

} catch (Exception ex) {

536

if (applicationEntityManager.getTransaction().isActive()) {

537

applicationEntityManager.getTransaction().rollback();

538

}

539

throw ex;

540

}

541

}

542

543

@Transactional

544

public void performContainerManagedOperation(User user) {

545

// Uses container-managed EntityManager (transaction-scoped)

546

containerEntityManager.persist(user);

547

548

// EntityManager is automatically managed by Spring transaction

549

}

550

551

public void performNonTransactionalQuery() {

552

// Shared EntityManager can be used outside transactions for read operations

553

List<User> users = sharedEntityManager

554

.createQuery("SELECT u FROM User u WHERE u.active = true", User.class)

555

.getResultList();

556

557

// Process users...

558

}

559

560

// Check if EntityManager is a proxy

561

public void inspectEntityManager() {

562

if (sharedEntityManager instanceof EntityManagerProxy) {

563

EntityManagerProxy proxy = (EntityManagerProxy) sharedEntityManager;

564

EntityManager target = proxy.getTargetEntityManager();

565

566

log.info("Using EntityManager proxy, target: {}", target.getClass().getName());

567

}

568

}

569

}

570

```

571

572

### Persistence Context Integration with Web Layer

573

574

Integration patterns for managing persistence contexts in web applications, including request-scoped EntityManager and lazy loading support.

575

576

```java { .api }

577

public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {

578

public static final String DEFAULT_ENTITY_MANAGER_FACTORY_BEAN_NAME = "entityManagerFactory";

579

580

public void setEntityManagerFactoryBeanName(String entityManagerFactoryBeanName);

581

public String getEntityManagerFactoryBeanName();

582

public void setPersistenceUnitName(String persistenceUnitName);

583

}

584

585

public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAccessor

586

implements AsyncWebRequestInterceptor {

587

public static final String PARTICIPATE_SUFFIX = ".PARTICIPATE";

588

589

public void preHandle(WebRequest request) throws DataAccessException;

590

public void postHandle(WebRequest request, ModelMap model);

591

public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException;

592

public void afterConcurrentHandlingStarted(WebRequest request);

593

}

594

```

595

596

#### Usage Example

597

598

```java

599

@Configuration

600

@EnableWebMvc

601

public class WebPersistenceConfig implements WebMvcConfigurer {

602

603

@Autowired

604

private EntityManagerFactory entityManagerFactory;

605

606

@Override

607

public void addInterceptors(InterceptorRegistry registry) {

608

OpenEntityManagerInViewInterceptor interceptor = new OpenEntityManagerInViewInterceptor();

609

interceptor.setEntityManagerFactory(entityManagerFactory);

610

611

registry.addWebRequestInterceptor(interceptor)

612

.addPathPatterns("/api/**") // Apply to specific paths

613

.excludePathPatterns("/api/health", "/api/metrics"); // Exclude certain paths

614

}

615

}

616

617

// Alternative: Using Filter approach

618

@WebFilter(urlPatterns = "/app/*")

619

public class CustomOpenEntityManagerInViewFilter extends OpenEntityManagerInViewFilter {

620

621

@Override

622

public void initFilterBean() {

623

setEntityManagerFactoryBeanName("primaryEntityManagerFactory");

624

setPersistenceUnitName("primaryPU");

625

}

626

627

@Override

628

protected boolean shouldNotFilterErrorDispatch() {

629

return false; // Include error dispatches

630

}

631

632

@Override

633

protected boolean shouldNotFilterAsyncDispatch() {

634

return false; // Include async dispatches

635

}

636

}

637

638

@RestController

639

@RequestMapping("/api/users")

640

public class UserController {

641

642

@PersistenceContext

643

private EntityManager entityManager;

644

645

@GetMapping("/{id}")

646

public UserDto getUser(@PathVariable Long id) {

647

// EntityManager is available throughout the request

648

User user = entityManager.find(User.class, id);

649

650

if (user != null) {

651

// Lazy associations can be accessed due to open EntityManager

652

user.getOrders().size(); // Triggers lazy loading

653

user.getProfile().getPreferences().size(); // Deep lazy loading

654

655

return convertToDto(user);

656

}

657

658

throw new EntityNotFoundException("User not found: " + id);

659

}

660

661

@GetMapping("/{id}/orders")

662

public List<OrderDto> getUserOrders(@PathVariable Long id) {

663

// Complex query with lazy loading support

664

User user = entityManager.find(User.class, id);

665

if (user != null) {

666

return user.getOrders().stream()

667

.map(this::convertOrderToDto)

668

.collect(Collectors.toList());

669

}

670

return Collections.emptyList();

671

}

672

}

673

674

// Async handling with persistence context

675

@RestController

676

@RequestMapping("/api/async")

677

public class AsyncController {

678

679

@PersistenceContext

680

private EntityManager entityManager;

681

682

@GetMapping("/users/{id}")

683

public CompletableFuture<UserDto> getUserAsync(@PathVariable Long id) {

684

// EntityManager is properly managed in async context

685

return CompletableFuture.supplyAsync(() -> {

686

User user = entityManager.find(User.class, id);

687

return convertToDto(user);

688

});

689

}

690

}

691

```

692

693

## Types

694

695

```java { .api }

696

import jakarta.persistence.EntityManager;

697

import jakarta.persistence.EntityManagerFactory;

698

import jakarta.persistence.EntityTransaction;

699

import jakarta.persistence.PersistenceContext;

700

import jakarta.persistence.PersistenceUnit;

701

import jakarta.persistence.PersistenceContextType;

702

import jakarta.persistence.PersistenceProperty;

703

import jakarta.persistence.SynchronizationType;

704

import jakarta.persistence.spi.PersistenceUnitInfo;

705

import jakarta.persistence.spi.PersistenceUnitTransactionType;

706

import jakarta.persistence.SharedCacheMode;

707

import jakarta.persistence.ValidationMode;

708

import org.springframework.beans.factory.config.BeanPostProcessor;

709

import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

710

import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;

711

import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;

712

import org.springframework.core.PriorityOrdered;

713

import org.springframework.beans.factory.BeanFactoryAware;

714

import org.springframework.web.context.request.WebRequest;

715

import org.springframework.ui.ModelMap;

716

import javax.sql.DataSource;

717

import java.net.URL;

718

import java.util.Map;

719

import java.util.Set;

720

import java.util.Properties;

721

import java.util.Collection;

722

import java.util.function.Predicate;

723

```