Configuring JPA with Spring and Container-Managed DataSources
Setting Up a JNDI DataSource
To use a cnotainer-managed database connection, define a bean that looks up the resource via JNDI. The following cnofiguration retrieves a MySQL data source bound to jdbc/mysql:
package com.example.setup;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.jndi.JndiObjectFactoryBean;
public class DatabaseConnectionConfig {
@Bean
public DataSource primaryDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean jndiFactory = new JndiObjectFactoryBean();
jndiFactory.setJndiName("jdbc/mysql");
jndiFactory.setResourceRef(true);
jndiFactory.setProxyInterface(DataSource.class);
jndiFactory.afterPropertiesSet();
return (DataSource) jndiFactory.getObject();
}
}
Initializing the JPA Entity Manager Factory
Next, configure the LocalContainerEntityManagerFactoryBean along with the JPA vendor adapter. This setup uses Hibernate as the persistence provider targeting MySQL.
package com.example.setup;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
@Configuration
@ComponentScan(basePackages = "com.example", excludeFilters = {
@Filter(type = FilterType.ANNOTATION, value = org.springframework.stereotype.Controller.class)
})
@Import(DatabaseConnectionConfig.class)
public class AppRootConfig {
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public JpaVendorAdapter hibernateAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setShowSql(true);
adapter.setGenerateDdl(false);
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL55Dialect");
return adapter;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter hibernateAdapter) {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource);
factory.setJpaVendorAdapter(hibernateAdapter);
factory.setPackagesToScan("com.example.model");
return factory;
}
}
Implementing a Data Access Object
The repsoitory class demonstrates how to persist an entity using the EntityManager obtained from the EntityManagerFactory, as well as performing raw SQL operations via JdbcOperations.
package com.example.repository;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.stereotype.Repository;
import com.example.model.Person;
@Repository
public class UserRepository {
@Autowired
private JdbcOperations jdbcOps;
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
public void createPerson() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
Person person = new Person();
person.setId(sdf.format(new Date()));
person.setName("name");
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(person);
transaction.commit();
entityManager.close();
}
public Map<String, String> insertRecord() {
int result = jdbcOps.update(
"INSERT INTO user(id, username, password) VALUES (?, ?, ?)",
"2", "user", "user"
);
Map<String, String> response = new HashMap<>();
response.put("affectedRows", String.valueOf(result));
return response;
}
public Map<String, String> updateRecord() {
int result = jdbcOps.update(
"UPDATE user SET username = ?, password = ? WHERE id = ?",
"admin", "admin", "1"
);
Map<String, String> response = new HashMap<>();
response.put("affectedRows", String.valueOf(result));
return response;
}
}