title: Spring Transactional annotation vs javax transactional
body: <p>I am working with Spring 4.3.x and Hibernate 5.2.x. Since hibernate 5 JPA is standard way to user ORM with spring, I created a config to use Hibernate with JPA.</p>
  
  <p>My spring configuration is,</p>
  
  <pre><code>import javax.persistence.EntityManagerFactory;
  import javax.sql.DataSource;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.PropertySource;
  import org.springframework.core.env.Environment;
  import org.springframework.orm.hibernate5.HibernateExceptionTranslator;
  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 com.zaxxer.hikari.HikariDataSource;
  
  @Configuration
  @ComponentScan(basePackages = { "com.example.reports" })
  @EnableTransactionManagement
  @PropertySource(value = { "classpath:application.properties" })
  public class SuperUserReportSpringConfiguration {
  
      @Autowired
      Environment environment;
  
      @Bean
      public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendeorAdapter) {
          LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
          entityManagerFactory.setDataSource(dataSource);
          entityManagerFactory.setJpaVendorAdapter(jpaVendeorAdapter);
          entityManagerFactory.setPackagesToScan("com.example.reports.domain");
          entityManagerFactory.setPersistenceUnitName("onlineDB");
          return entityManagerFactory;
      }
  
      @Bean
      public JpaVendorAdapter jpaVendorAdapter() {
          HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
          adapter.setShowSql(false);
          adapter.setDatabasePlatform("org.hibernate.dialect.DB2400Dialect");
          return adapter;
      }
  
      @Bean
      DataSource dataSource() {
          HikariDataSource ds = new HikariDataSource();
          ds.setPoolName("hikariCP");
          ds.setDriverClassName(this.environment.getProperty("jdbc.as400.db2.db.driver.classname"));
          ds.setJdbcUrl(this.environment.getProperty("jdbc.as400.db2.db.url"));
          ds.setUsername(this.environment.getProperty("jdbc.as400.db2.db.username"));
          ds.setPassword(this.environment.getProperty("jdbc.as400.db2.db.password"));
          ds.setMaximumPoolSize(10);
          return ds;
      }
  
      @Bean
      public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
          JpaTransactionManager transactionManager = new JpaTransactionManager(emf);
          return transactionManager;
      }
  
      @Bean
      public HibernateExceptionTranslator hibernateExceptionTranslator() {
          return new HibernateExceptionTranslator();
      }
  
  }
  </code></pre>
  
  <p>And I try to use <code>@Transactional</code> from javax.transaction.Transactional and org.springframework.transaction.annotation.Transactional</p>
  
  <p>In both the case, transaction manager is not working and I am getting error when trying to get child element from User entity,</p>
  
  <p><code>org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.reports.domain.User.userInetAddrs, could not initialize proxy - no Session</code></p>
  
  <p>I am not sure if I am missing any configuration.</p>
  
  <p>Hibernate entity,</p>
  
  <p><code>@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
   private Set&lt;UserInetAddr&gt; userInetAddrs = new HashSet&lt;UserInetAddr&gt;(0);</code></p>
  
  <p>Service class with <code>@Transactional</code></p>
  
  <pre><code>User user = superUserReportDao.getUserSecurityRoles(id);
  user.getUserInetAddrs().forEach(inetAddress -&gt; {
  
  });
  </code></pre>
  
  <p>And DAO Method with <code>@Transactional</code></p>
  
  <pre><code>public User getUser(int userSeqId) {
      return entityManager.find(User.class, userSeqId);
  }
  </code></pre>
  
  <p>DAO Class transaction,</p>
  
  <pre><code>@Repository("superUserReportDao")
  @Slf4j
  @Transactional
  public class SuperUserReportDaoImpl implements SuperUserReportDao {
  
      @PersistenceContext(unitName="onlineDB")
      private EntityManager onlineEntityManager;
  </code></pre>
  
  <p>And Service Class,</p>
  
  <pre><code>@Service("superUserReportService")
  @Slf4j
  public class SuperUserReportServiceImpl implements SuperUserReportService {
  
      @Resource(name = "superUserReportDao")
      private SuperUserReportDao superUserReportDao;
  
      public void generateSuperUserReport() throws SQLException {
  
          // -- generate Customer Super user report
          generateSuperUserEmail(UserType.CUSTOMER);
  
      }
  
      @Transactional
      private void generateSuperUserEmail(UserType userType) throws SQLException {
  ...
  </code></pre>
  
  <p>And my main class,</p>
  
  <pre><code>@Slf4j
  @Component
  public class SuperUserReportMain {
  
      @Resource(name = "superUserReportService")
      SuperUserReportService superUserReportService;
  
      /**
       * @param args
       * @throws SQLException 
       */
      public static void main(String[] args) throws SQLException {
          ApplicationContext context = new AnnotationConfigApplicationContext(SuperUserReportSpringConfiguration.class);
  
          SuperUserReportMain reportMain = context.getBean(SuperUserReportMain.class);
          reportMain.generateSuperUserReport();
  
          ((AnnotationConfigApplicationContext)context).close();
  
      }
  
      public void generateSuperUserReport() throws SQLException {
          superUserReportService.generateSuperUserReport();
      }
  
  }
  </code></pre>