Here is my take at configuring Spring programmatically to support the more popular JPA providers out there: Hibernate, EclipseLink, OpenJpa and DataNucleus.
I am assuming you already know how to programmatically configure a data source, as well as how to use the @Configuration annotation. I’m just providing the @Bean definition for the entity manager factory.
Shared code
The following bean definition code provides common code shared by all JPA providers, and then calls configureProvider: we will isolate all provider specific code in that method.
@Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws PropertyVetoException { LocalContainerEntityManagerFactoryBean result = new LocalContainerEntityManagerFactoryBean(); // loadTimeWeaver will be available if // @EnableLoadTimeWeaving is specified in this // config class (annotated with @Configuration) result.setLoadTimeWeaver(loadTimeWeaver); // coreDs should be a DataSource bean, // configured elsewhere. result.setDataSource(coreDs); Properties jpaProperties = new Properties(); // ** Configuration common to all JPA 2.0 managers // coreDsDriverName is the database driver name! // used to configure the datasource AND the // JPA provider jpaProperties.put( "javax.persistence.jdbc.driver", coreDsDriverName); // ** Provider specific config isolated here configureProvider(jpaProperties, result); result.setJpaProperties(jpaProperties); result.afterPropertiesSet(); return result; }
With this configuration you will have to provide your persistence.xml file. Just do not put a <provider> entry there: it will not be needed, we are specifying the provider programmatically.
However, if you want to remove the persistence.xml file, you can do that by specifying the packages to scan for entities programmatically, calling result.setPackagesToScan.
EclipseLink configuration
This is my very basic EclipseLink configuration. You should add EclipseLink specific configuration properties to jpaProperties, and provide configuration data to the entity manager factory bean (emf) so that it can instantiate the right provider.
private void configureProvider(Properties jpaProperties, LocalEntityManagerFactoryBean emf) { // We want EclipseLink to recreate the database schema jpaProperties.put("eclipselink.ddl-generation", "drop-and-create-tables"); emf.setJpaVendorAdapter( new EclipseLinkJpaVendorAdapter()); }
Hibernate configuration
This is my very basic Hibernate configuration:
private void configureProvider(Properties jpaProperties, LocalEntityManagerFactoryBean emf) { // We want Hibernate to recreate the database schema jpaProperties.put( org.hibernate.cfg.Environment.HBM2DDL_AUTO, "create-drop"); // And we want Hibernate! emf.setJpaVendorAdapter( new HibernateJpaVendorAdapter()); }
OpenJpa configuration
OpenJpa basic configuration follows:
private void configureProvider(Properties jpaProperties, LocalEntityManagerFactoryBean emf) { // We want EclipseLink to recreate the database schema jpaProperties.put("openjpa.jdbc.SynchronizeMappings", "buildSchema"); jpaProperties.put("openjpa.InitializeEagerly", "true"); emf.setJpaVendorAdapter( new OpenJpaVendorAdapter()); }
DataNucleus configuration
If you are using DataNucleus as your persistence provider, you are a bit out of luck, as Spring does not implement a vendor adapter for DataNucleus. We need to use a different approach, as follows.
private void configureProvider(Properties jpaProperties, LocalEntityManagerFactoryBean emf) { // We want DataNucleus to recreate the database schema jpaProperties.put("datanucleus.autoCreateSchema", "true"); emf.setPersistenceProviderClass( org.datanucleus.api.jpa.PersistenceProviderImpl.class); }
Thats’ it!