0

I am using @PersistenceContext as of now and working fine. However the same application need to be used in Junit context as well. I want @PersistenceContext to be changed to @PersistenceUnit in DaoImpl classes when Junit test cases are running. How to do that?

Using the following versions in my application

<springframework.version>4.2.5.RELEASE</springframework.version>
<hibernate.version>5.1.0.Final</hibernate.version>
<hibernate.validator.version>5.2.4.Final</hibernate.validator.version>
<mysql.connector.version>6.0.3</mysql.connector.version>
<junit.version>4.12</junit.version>

Hibernate Configuration is:

package com.rsa.springwebclasses.configuration.db;

import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import ch.qos.logback.classic.Logger;

@Configuration
@EnableTransactionManagement
@PropertySources({
  @PropertySource("classpath:hibernate/hibernate.properties"),
  @PropertySource("classpath:mysql/mysql.properties")
})
public class HibernateConfiguration {
  Logger logger = (Logger) LoggerFactory.getLogger(HibernateConfiguration.class);

  @Autowired
  Environment env;

private Properties getHibernateProperties() {
    Properties hprop = new Properties();
    hprop.put("hibernate.dialect", env.getRequiredProperty("mysql.hibernate.dialect"));
    hprop.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
    hprop.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
    logger.info("Hibernate properties: " + hprop.toString());
    return hprop;
}

private Properties getMysqlProperties() {
    Properties mySqlProp = new Properties();
    mySqlProp.put("jdbc.driverClassName", env.getRequiredProperty("mysql.jdbc.driverClassName"));
    mySqlProp.put("jdbc.url", env.getRequiredProperty("test.mysql.jdbc.url"));
    mySqlProp.put("jdbc.username", env.getRequiredProperty("test.mysql.jdbc.username"));
    mySqlProp.put("jdbc.password", env.getRequiredProperty("test.mysql.jdbc.password"));
    logger.info("MySQL properties: " + mySqlProp.toString());
    return mySqlProp;
}

@Bean
public DataSource getDataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    Properties dbProp = this.getMysqlProperties();
    dataSource.setDriverClassName(dbProp.getProperty("jdbc.driverClassName"));
    dataSource.setUrl(dbProp.getProperty("jdbc.url"));
    dataSource.setUsername(dbProp.getProperty("jdbc.username"));
    dataSource.setPassword(dbProp.getProperty("jdbc.password"));
    logger.info("DataSource object is created.");
    return dataSource;
}

@Bean
public PlatformTransactionManager getTransactionManager(EntityManagerFactory emf) {
    JpaTransactionManager jtm = new JpaTransactionManager();
    jtm.setEntityManagerFactory(emf);
    logger.info("PlatformTransactionManager is initialized with JpaTransactionManager");
    return jtm;
}

@Bean
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
    LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
    emfb.setDataSource(getDataSource());
    emfb.setPackagesToScan(new String[] {"com.rsa.springwebclasses.model"});
    JpaVendorAdapter vendor = new HibernateJpaVendorAdapter();
    emfb.setJpaVendorAdapter(vendor);
    emfb.setJpaProperties(getHibernateProperties());
    logger.info("LocalContainerEntityManagerFactoryBean created: PersistentUnit Name: " + emfb.getJpaVendorAdapter().toString());
    return emfb;
}

}

My DaoImpl class is:

package com.rsa.springwebclasses.dao.impl;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.rsa.springwebclasses.dao.UserDao;
import com.rsa.springwebclasses.model.User;

import ch.qos.logback.classic.Logger;

@Repository("userDao")
public class UserDaoImpl implements UserDao {
   Logger logger = (Logger) LoggerFactory.getLogger(UserDaoImpl.class);

  **@PersistenceContext**
  EntityManager em;

public List<User> findAllUsers() {
    logger.debug("In findAllUsers method.");
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<User> criteria = cb.createQuery(User.class);
    Root<User> user = criteria.from(User.class);
    criteria.select(user).orderBy(cb.asc(user.get("username")));
    logger.debug("Exit findAllUsers method");
    return em.createQuery(criteria).getResultList();
  }
}

While injecting EntityManager, @PersistenceContext is hard coded. However the same DaoImpl class need to be used for Junit test cases as well. With Junit I prefer to use transaction type as RESOUCE_LOCAL which is possible only with @PersistenceUnit. Is it possible to have a different annotation in DaoImpl class and assign @PersistenceContext or @PersistenceUnit while application is loading or already running?

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
SVGK Raju
  • 49
  • 6
  • Your understanding is wrong... Just leave the `@PersistenceContext` as is. See http://stackoverflow.com/questions/21038706/persistenceunit-vs-persistencecontext. In short `@PersistenceContext` is for `EntityManager` injection, `@PersistenceUnit` is for `EntityManagerFactory` injection. Next to that you are already using local transactions as you have a `JpaTransactionManager` and not a distributed one like JTA. – M. Deinum Aug 05 '16 at 07:54
  • Correct. Thanks for you post. I added **@Rollback** annotation in Junit test. Which worked beautifully and satisfied my requirement. – SVGK Raju Aug 05 '16 at 16:30

0 Answers0