Spring with JPA using Hibernate

As we know, JPA is not an implementation; it is the specification for persistence. The Hibernate framework follows all of the specifications, and it also has its own additional features. Using the JPA specification in an application enables us to easily switch the persistence provider later if needed.

To use Hibernate on its own requires SessionFactory, and to use Hibernate with JPA requires EntityManager. We are going to use JPA, and the following is the Spring Java-based Hibernate JPA configuration:

@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-hibernate.properties" })
@ComponentScan({ "com.packt.springhighperformance.ch6.bankingapp" })
public class PersistenceJPAConfig {

@Autowired
private Environment env;

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new
LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] {
"com.packt.springhighperformance
.ch6.bankingapp.model" });

JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());

return em;
}

@Bean
public BeanPostProcessor persistenceTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}

@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(this.env.get
Property("jdbc.driverClassName"));
dataSource.setUrl(this.env.getProperty("jdbc.url"));
dataSource.setUsername(this.env.getProperty("jdbc.user"));
dataSource.setPassword(this.env.getProperty("jdbc.password"));
return dataSource;
}

@Bean
public PlatformTransactionManager
transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new
JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor
exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}

private Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto",
this.env.getProperty("hibernate.hbm2ddl.auto"));
properties.setProperty("hibernate.dialect",
this.env.getProperty("hibernate.dialect"));
properties.setProperty("hibernate.generate_statistics",
this.env.getProperty("hibernate.generate_statistics"));
properties.setProperty("hibernate.show_sql",
this.env.getProperty("hibernate.show_sql"));
properties.setProperty("hibernate.cache.use_second_level_cache",
this.env.getProperty("hibernate.cache.use_second_level_cache"));
properties.setProperty("hibernate.cache.use_query_cache",
this.env.getProperty("hibernate.cache.use_query_cache"));
properties.setProperty("hibernate.cache.region.factory_class",
this.env.getProperty("hibernate.cache.region.factory_class"));

return properties;
}
}

In the preceding configuration, we configured EntityManager using the LocalContainerEntityManagerFactoryBean class. We set DataSource to provide information on where to find our database. As we are using JPA, which is the specification followed by a different vendor, we specified which vendor we are using in our application by setting HibernateJpaVendorAdapter and setting vendor-specific additional properties.

Now that we have configured the JPA-based ORM framework in our application, let's see how to create a DAO in our application when using ORM.

The following is the AbstractJpaDAO class, having the basic common method required for all of our DAOs:

public abstract class AbstractJpaDAO<T extends Serializable> {

private Class<T> clazz;

@PersistenceContext
private EntityManager entityManager;

public final void setClazz(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}

public T findOne(final Integer id) {
return entityManager.find(clazz, id);
}

@SuppressWarnings("unchecked")
public List<T> findAll() {
return entityManager.createQuery("from " +
clazz.getName()).getResultList();
}

public void create(final T entity) {
entityManager.persist(entity);
}

public T update(final T entity) {
return entityManager.merge(entity);
}

public void delete(final T entity) {
entityManager.remove(entity);
}

public void deleteById(final Long entityId) {
final T entity = findOne(entityId);
delete(entity);
}
}

The following is the AccountDAO class, which manages the Account entity-related method:

@Repository
public class AccountDAO extends AbstractJpaDAO<Account> implements IAccountDAO {

public AccountDAO() {
super();
setClazz(Account.class);
}
}

The preceding examples of DAO implementation are pretty basic, and is what we generally do in our applications. In case DAO throws an exception such as PersistenceException, and instead of showing an exception to the user, we would want to show the right, human-readable message to the end users. To provide a readable message when an exception occurs, Spring provides a translator which we need to define in our configuration class as follows:

@Bean
public BeanPostProcessor persistenceTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}

The BeanPostProcessor command works when we annotate our DAOs with the @Repository annotation. The PersistenceExceptionTranslationPostProcessor bean will act as an advisor for the beans, which are annotated with the @Repository annotation. Remember that we learned about advises in Chapter 3, Tuning Aspect-Oriented Programming. When advised, it will re-throw Spring-specific unchecked data access exceptions caught in the code.

So, this was the basic configuration of Spring JPA using Hibernate. Now, let's see the Spring Data configuration.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset