Spring Transactional annotation vs javax transactional

时间:2017-08-21 16:39:52

标签: java spring hibernate jpa transactions

我正在使用Spring 4.3.x和Hibernate 5.2.x.由于hibernate 5 JPA是使用Spring的用户ORM的标准方法,因此我创建了一个使用Hibernate和JPA的配置。

我的弹簧配置是,

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();
    }

}

我尝试使用javax.transaction.Transactional和org.springframework.transaction.annotation.Transactional

中的@Transactional

在这两种情况下,事务管理器都不工作,我在尝试从用户实体获取子元素时遇到错误,

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.reports.domain.User.userInetAddrs, could not initialize proxy - no Session

我不确定我是否缺少任何配置。

Hibernate实体,

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user") private Set<UserInetAddr> userInetAddrs = new HashSet<UserInetAddr>(0);

@Transactional

的服务类
User user = superUserReportDao.getUserSecurityRoles(id);
user.getUserInetAddrs().forEach(inetAddress -> {

});

使用@Transactional

的DAO方法
public User getUser(int userSeqId) {
    return entityManager.find(User.class, userSeqId);
}

DAO班级交易,

@Repository("superUserReportDao")
@Slf4j
@Transactional
public class SuperUserReportDaoImpl implements SuperUserReportDao {

    @PersistenceContext(unitName="onlineDB")
    private EntityManager onlineEntityManager;

服务类,

@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 {
...

我的主要班级,

@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();
    }

}

0 个答案:

没有答案