0
# JPA Integration
1
2
Spring ORM provides comprehensive integration with the Java Persistence API (JPA), offering EntityManagerFactory configuration, transaction management, shared EntityManager creation, vendor-specific adaptations, and annotation-driven dependency injection. This integration supports both container-managed and application-managed persistence contexts with full Spring lifecycle management.
3
4
## Capabilities
5
6
### EntityManagerFactory Configuration
7
8
Configure JPA EntityManagerFactory instances with Spring lifecycle management, automatic entity scanning, vendor-specific properties, and DataSource integration.
9
10
```java { .api }
11
public abstract class AbstractEntityManagerFactoryBean implements FactoryBean<EntityManagerFactory>,
12
BeanClassLoaderAware, BeanNameAware, InitializingBean, DisposableBean, EntityManagerFactoryInfo, Serializable {
13
public void setJpaVendorAdapter(JpaVendorAdapter jpaVendorAdapter);
14
public JpaVendorAdapter getJpaVendorAdapter();
15
public void setPersistenceProvider(PersistenceProvider persistenceProvider);
16
public void setJpaProperties(Properties jpaProperties);
17
public void setEntityManagerInitializer(Consumer<EntityManager> entityManagerInitializer);
18
public abstract EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException;
19
}
20
21
public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManagerFactoryBean
22
implements ResourceLoaderAware, LoadTimeWeaverAware {
23
public void setPersistenceUnitManager(PersistenceUnitManager persistenceUnitManager);
24
public void setPersistenceXmlLocation(String persistenceXmlLocation);
25
public void setManagedTypes(PersistenceManagedTypes managedTypes);
26
public void setPackagesToScan(String... packagesToScan);
27
public void setMappingResources(String... mappingResources);
28
public void setDataSource(DataSource dataSource);
29
public void setJtaDataSource(DataSource jtaDataSource);
30
public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver);
31
public EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException;
32
}
33
34
public class LocalEntityManagerFactoryBean extends AbstractEntityManagerFactoryBean {
35
public void setDataSource(DataSource dataSource);
36
public DataSource getDataSource();
37
38
protected EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException;
39
}
40
```
41
42
#### Usage Example
43
44
```java
45
@Configuration
46
@EnableJpaRepositories
47
public class JpaConfig {
48
49
@Bean
50
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
51
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
52
em.setDataSource(dataSource());
53
em.setPackagesToScan("com.example.entity");
54
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
55
56
Properties jpaProperties = new Properties();
57
jpaProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
58
jpaProperties.setProperty("hibernate.hbm2ddl.auto", "validate");
59
jpaProperties.setProperty("hibernate.show_sql", "false");
60
em.setJpaProperties(jpaProperties);
61
62
// Custom EntityManager initialization
63
em.setEntityManagerInitializer(entityManager -> {
64
entityManager.setProperty("hibernate.jdbc.batch_size", 20);
65
});
66
67
return em;
68
}
69
70
@Bean
71
public DataSource dataSource() {
72
HikariDataSource dataSource = new HikariDataSource();
73
dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
74
dataSource.setUsername("user");
75
dataSource.setPassword("password");
76
return dataSource;
77
}
78
}
79
```
80
81
### JPA Transaction Management
82
83
Dedicated transaction management for JPA with EntityManager lifecycle integration, resource synchronization, and transaction-aware EntityManager creation.
84
85
```java { .api }
86
public class JpaTransactionManager extends AbstractPlatformTransactionManager
87
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
88
public JpaTransactionManager();
89
public JpaTransactionManager(EntityManagerFactory emf);
90
public void setEntityManagerFactory(EntityManagerFactory emf);
91
public EntityManagerFactory getEntityManagerFactory();
92
public void setPersistenceUnitName(String persistenceUnitName);
93
public void setJpaProperties(Properties jpaProperties);
94
public void setDataSource(DataSource dataSource);
95
public void setJpaDialect(JpaDialect jpaDialect);
96
public void setEntityManagerInitializer(Consumer<EntityManager> entityManagerInitializer);
97
}
98
99
public abstract class EntityManagerFactoryAccessor implements BeanFactoryAware {
100
public void setEntityManagerFactory(EntityManagerFactory emf);
101
public EntityManagerFactory getEntityManagerFactory();
102
public EntityManagerFactory obtainEntityManagerFactory();
103
}
104
```
105
106
#### Usage Example
107
108
```java
109
@Configuration
110
@EnableTransactionManagement
111
public class TransactionConfig {
112
113
@Bean
114
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
115
JpaTransactionManager txManager = new JpaTransactionManager();
116
txManager.setEntityManagerFactory(entityManagerFactory);
117
118
// Optional: Set DataSource for connection-level transaction synchronization
119
txManager.setDataSource(dataSource());
120
121
// Optional: Custom JPA dialect for vendor-specific behavior
122
txManager.setJpaDialect(new HibernateJpaDialect());
123
124
return txManager;
125
}
126
}
127
128
@Service
129
@Transactional
130
public class UserService {
131
132
@PersistenceContext
133
private EntityManager entityManager;
134
135
public void createUser(String name, String email) {
136
User user = new User();
137
user.setName(name);
138
user.setEmail(email);
139
entityManager.persist(user);
140
// Transaction automatically commits on method completion
141
}
142
143
@Transactional(readOnly = true)
144
public User findUser(Long id) {
145
return entityManager.find(User.class, id);
146
}
147
}
148
```
149
150
### Shared EntityManager Creation
151
152
Create thread-safe EntityManager proxies that automatically participate in Spring-managed transactions and handle proper resource lifecycle.
153
154
```java { .api }
155
public abstract class SharedEntityManagerCreator {
156
public static EntityManager createSharedEntityManager(EntityManagerFactory emf);
157
public static EntityManager createSharedEntityManager(EntityManagerFactory emf, Map<?, ?> properties);
158
public static EntityManager createSharedEntityManager(EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction);
159
public static EntityManager createSharedEntityManager(EntityManagerFactory emf, Map<?, ?> properties, Class<?>... entityManagerInterfaces);
160
public static EntityManager createSharedEntityManager(EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction, Class<?>... entityManagerInterfaces);
161
}
162
163
public class SharedEntityManagerBean extends EntityManagerFactoryAccessor
164
implements FactoryBean<EntityManager>, InitializingBean {
165
public void setPersistenceUnitName(String persistenceUnitName);
166
public void setJpaProperties(Properties jpaProperties);
167
public EntityManager getObject();
168
public Class<? extends EntityManager> getObjectType();
169
}
170
```
171
172
#### Usage Example
173
174
```java
175
@Configuration
176
public class EntityManagerConfig {
177
178
@Bean
179
public EntityManager sharedEntityManager(EntityManagerFactory entityManagerFactory) {
180
Map<String, Object> properties = new HashMap<>();
181
properties.put("hibernate.jdbc.batch_size", 25);
182
properties.put("hibernate.order_inserts", true);
183
184
return SharedEntityManagerCreator.createSharedEntityManager(
185
entityManagerFactory,
186
properties
187
);
188
}
189
}
190
191
@Repository
192
public class ProductRepository {
193
194
@Autowired
195
private EntityManager entityManager; // Shared EntityManager
196
197
@Transactional
198
public void saveProducts(List<Product> products) {
199
for (int i = 0; i < products.size(); i++) {
200
entityManager.persist(products.get(i));
201
if (i % 25 == 0) {
202
entityManager.flush();
203
entityManager.clear();
204
}
205
}
206
}
207
}
208
```
209
210
### JPA Vendor Adapters
211
212
Vendor-specific implementations providing optimal integration with different JPA providers including Hibernate and EclipseLink.
213
214
```java { .api }
215
public interface JpaVendorAdapter {
216
PersistenceProvider getPersistenceProvider();
217
String getPersistenceProviderRootPackage();
218
Map<String, ?> getJpaPropertyMap(PersistenceUnitInfo pui);
219
JpaDialect getJpaDialect();
220
Class<? extends EntityManagerFactory> getEntityManagerFactoryInterface();
221
void postProcessEntityManagerFactory(EntityManagerFactory emf);
222
}
223
224
public abstract class AbstractJpaVendorAdapter implements JpaVendorAdapter {
225
public void setDatabase(Database database);
226
public Database getDatabase();
227
public void setDatabasePlatform(String databasePlatform);
228
public void setGenerateDdl(boolean generateDdl);
229
public void setShowSql(boolean showSql);
230
}
231
232
public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
233
public void setPrepareConnection(boolean prepareConnection);
234
public PersistenceProvider getPersistenceProvider();
235
public String getPersistenceProviderRootPackage();
236
public Map<String, Object> getJpaPropertyMap(PersistenceUnitInfo pui);
237
public Map<String, Object> getJpaPropertyMap();
238
public HibernateJpaDialect getJpaDialect();
239
public Class<? extends EntityManagerFactory> getEntityManagerFactoryInterface();
240
public Class<? extends EntityManager> getEntityManagerInterface();
241
242
protected Class<?> determineDatabaseDialectClass(Database database);
243
}
244
245
public class EclipseLinkJpaVendorAdapter extends AbstractJpaVendorAdapter {
246
public PersistenceProvider getPersistenceProvider();
247
public Map<String, Object> getJpaPropertyMap();
248
public EclipseLinkJpaDialect getJpaDialect();
249
public Class<? extends EntityManager> getEntityManagerInterface();
250
251
protected String determineTargetDatabaseName(Database database);
252
}
253
254
public enum Database {
255
DEFAULT, DB2, DERBY, H2, HANA, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER, SYBASE
256
}
257
```
258
259
#### Usage Example
260
261
```java
262
@Configuration
263
public class VendorConfig {
264
265
@Bean
266
public JpaVendorAdapter hibernateVendorAdapter() {
267
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
268
adapter.setDatabase(Database.POSTGRESQL);
269
adapter.setGenerateDdl(false);
270
adapter.setShowSql(true);
271
adapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQL95Dialect");
272
return adapter;
273
}
274
275
@Bean
276
public JpaVendorAdapter eclipseLinkVendorAdapter() {
277
EclipseLinkJpaVendorAdapter adapter = new EclipseLinkJpaVendorAdapter();
278
adapter.setDatabase(Database.MYSQL);
279
adapter.setGenerateDdl(true);
280
adapter.setShowSql(false);
281
return adapter;
282
}
283
}
284
```
285
286
### JPA Dialects
287
288
Vendor-specific dialect implementations that provide access to advanced features like JDBC connections and transaction customization.
289
290
```java { .api }
291
public interface JpaDialect extends PersistenceExceptionTranslator {
292
Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) throws PersistenceException, SQLException, TransactionException;
293
Object prepareTransaction(EntityManager entityManager, boolean readOnly, String name) throws PersistenceException;
294
void cleanupTransaction(Object transactionData);
295
ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly) throws PersistenceException, SQLException;
296
void releaseJdbcConnection(ConnectionHandle conHandle, EntityManager entityManager) throws PersistenceException, SQLException;
297
}
298
299
public class DefaultJpaDialect implements JpaDialect, Serializable {
300
public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) throws PersistenceException, SQLException, TransactionException;
301
public Object prepareTransaction(EntityManager entityManager, boolean readOnly, String name) throws PersistenceException;
302
public void cleanupTransaction(Object transactionData);
303
public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly) throws PersistenceException, SQLException;
304
public void releaseJdbcConnection(ConnectionHandle conHandle, EntityManager entityManager) throws PersistenceException, SQLException;
305
public DataAccessException translateExceptionIfPossible(RuntimeException ex);
306
}
307
308
public class HibernateJpaDialect extends DefaultJpaDialect {
309
public Object beginTransaction(EntityManager entityManager, TransactionDefinition definition) throws PersistenceException, SQLException, TransactionException;
310
public ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly) throws PersistenceException, SQLException;
311
public DataAccessException translateExceptionIfPossible(RuntimeException ex);
312
}
313
314
public class EclipseLinkJpaDialect extends DefaultJpaDialect {
315
// EclipseLink-specific implementations
316
}
317
```
318
319
### EntityManager Utilities
320
321
Helper utilities for obtaining transactional EntityManager instances, applying transaction timeouts, and converting JPA exceptions.
322
323
```java { .api }
324
public abstract class EntityManagerFactoryUtils {
325
public static final int ENTITY_MANAGER_SYNCHRONIZATION_ORDER = DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER + 100;
326
327
public static EntityManager getTransactionalEntityManager(EntityManagerFactory emf) throws DataAccessException;
328
public static EntityManager getTransactionalEntityManager(EntityManagerFactory emf, Map<?, ?> properties) throws DataAccessException;
329
public static EntityManager doGetTransactionalEntityManager(EntityManagerFactory emf, Map<?, ?> properties) throws DataAccessException;
330
public static void applyTransactionTimeout(Query query, EntityManagerFactory emf);
331
public static DataAccessException convertJpaAccessExceptionIfPossible(RuntimeException ex);
332
public static void closeEntityManager(EntityManager em);
333
}
334
335
public class EntityManagerHolder extends ResourceHolderSupport {
336
public EntityManagerHolder(EntityManager entityManager);
337
public EntityManager getEntityManager();
338
public void setTransactionActive(boolean transactionActive);
339
public boolean isTransactionActive();
340
}
341
```
342
343
#### Usage Example
344
345
```java
346
@Component
347
public class CustomDataAccess {
348
349
@Autowired
350
private EntityManagerFactory entityManagerFactory;
351
352
public void performCustomOperation() {
353
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
354
try {
355
Query query = em.createQuery("SELECT u FROM User u WHERE u.active = true");
356
EntityManagerFactoryUtils.applyTransactionTimeout(query, entityManagerFactory);
357
358
@SuppressWarnings("unchecked")
359
List<User> users = query.getResultList();
360
361
// Process users...
362
363
} catch (RuntimeException ex) {
364
DataAccessException dae = EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(ex);
365
if (dae != null) {
366
throw dae;
367
}
368
throw ex;
369
}
370
}
371
}
372
```
373
374
### Extended EntityManager Support
375
376
Support for both application-managed and container-managed EntityManager patterns with proper lifecycle management.
377
378
```java { .api }
379
public abstract class ExtendedEntityManagerCreator {
380
public static EntityManager createApplicationManagedEntityManager(EntityManager rawEntityManager, EntityManagerFactoryInfo emfInfo);
381
public static EntityManager createContainerManagedEntityManager(EntityManagerFactory emf, Map<?, ?> properties, boolean synchronizedWithTransaction);
382
}
383
384
public interface EntityManagerProxy extends EntityManager {
385
EntityManager getTargetEntityManager();
386
}
387
388
public interface EntityManagerFactoryInfo {
389
PersistenceUnitInfo getPersistenceUnitInfo();
390
String getPersistenceUnitName();
391
DataSource getDataSource();
392
JpaDialect getJpaDialect();
393
EntityManager createNativeEntityManager(Map<String, Object> properties);
394
}
395
```
396
397
### JPA Exception Handling
398
399
JPA-specific exception classes that extend Spring's DataAccessException hierarchy for consistent error handling.
400
401
```java { .api }
402
public class JpaObjectRetrievalFailureException extends ObjectRetrievalFailureException {
403
public JpaObjectRetrievalFailureException(EntityNotFoundException ex);
404
}
405
406
public class JpaOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException {
407
public JpaOptimisticLockingFailureException(OptimisticLockException ex);
408
}
409
410
public class JpaSystemException extends UncategorizedDataAccessException {
411
public JpaSystemException(PersistenceException ex);
412
}
413
```
414
415
## Web Integration Support
416
417
JPA-specific web integration components for managing persistence contexts across HTTP requests.
418
419
```java { .api }
420
public class OpenEntityManagerInViewFilter extends OncePerRequestFilter {
421
public static final String DEFAULT_ENTITY_MANAGER_FACTORY_BEAN_NAME = "entityManagerFactory";
422
423
public void setEntityManagerFactoryBeanName(String entityManagerFactoryBeanName);
424
public String getEntityManagerFactoryBeanName();
425
public void setPersistenceUnitName(String persistenceUnitName);
426
}
427
428
public class OpenEntityManagerInViewInterceptor extends EntityManagerFactoryAccessor
429
implements AsyncWebRequestInterceptor {
430
public static final String PARTICIPATE_SUFFIX = ".PARTICIPATE";
431
432
public void preHandle(WebRequest request) throws DataAccessException;
433
public void postHandle(WebRequest request, ModelMap model);
434
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException;
435
}
436
```
437
438
#### Usage Example
439
440
```java
441
@Configuration
442
public class WebConfig implements WebMvcConfigurer {
443
444
@Override
445
public void addInterceptors(InterceptorRegistry registry) {
446
OpenEntityManagerInViewInterceptor interceptor = new OpenEntityManagerInViewInterceptor();
447
interceptor.setEntityManagerFactory(entityManagerFactory);
448
registry.addWebRequestInterceptor(interceptor);
449
}
450
}
451
452
// Or as a Servlet Filter
453
@WebFilter("/*")
454
public class CustomOpenEntityManagerInViewFilter extends OpenEntityManagerInViewFilter {
455
456
@Override
457
public void initFilterBean() {
458
setEntityManagerFactoryBeanName("customEntityManagerFactory");
459
setPersistenceUnitName("customPU");
460
}
461
}
462
```
463
464
## Types
465
466
```java { .api }
467
import jakarta.persistence.EntityManager;
468
import jakarta.persistence.EntityManagerFactory;
469
import jakarta.persistence.PersistenceException;
470
import jakarta.persistence.Query;
471
import jakarta.persistence.EntityNotFoundException;
472
import jakarta.persistence.OptimisticLockException;
473
import jakarta.persistence.spi.PersistenceProvider;
474
import jakarta.persistence.spi.PersistenceUnitInfo;
475
import javax.sql.DataSource;
476
import java.util.Map;
477
import java.util.Properties;
478
import java.util.function.Consumer;
479
import org.springframework.transaction.TransactionDefinition;
480
import org.springframework.transaction.PlatformTransactionManager;
481
import org.springframework.dao.DataAccessException;
482
import org.springframework.jdbc.datasource.ConnectionHandle;
483
import org.springframework.orm.jpa.vendor.Database;
484
```