Spring/Hibernate @Transactional on 方法阻止更新 SQL

Spring/Hibernate @Transactional on method prevents update SQL

我有一个执行加载、更新 属性 并调用 saveOrUpdate(bean) 的 Junit 测试方法。

它的行为很奇怪,因为将 @Transactional 添加到方法签名会阻止执行更新 SQL(日志中未生成 SQL)。

删除 @Transactional 并生成更新 SQL 并更新数据库。

@Configuration
@EnableTransactionManagement
@PropertySource(
        {
            "classpath:jdbc.properties",
            "classpath:hibernate.properties"
        })
@ComponentScan(value = "com.savant.test.spring.donorservice.core.dao")
public class ApplicationContext {


    @Bean(destroyMethod = "close")
    @Autowired
    public DataSource dataSource() {

        // Hikari is a connection pool manager.
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        dataSource.setJdbcUrl(env.getProperty("jdbc.url"));
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setIsolateInternalQueries(true);
        System.out.println(dataSource);

        dataSource.setConnectionTestQuery("SELECT count(*) from system.onerow");
        dataSource.setMaximumPoolSize(3);
        dataSource.setAutoCommit(false);

        return dataSource;
    }


    @Bean
    @Autowired
    public LocalSessionFactoryBean sessionFactory(DataSource datasouce) {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(datasouce);
        sessionFactory.setPackagesToScan(package_to_scan);
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }


    private Properties hibernateProperties() {
        Properties hibernateProperties = new Properties();
        hibernateProperties.put(hibernate_dialect, env.getProperty(hibernate_dialect));
        hibernateProperties.put(hibernate_current_session_context_class, env.getProperty(hibernate_current_session_context_class));
        hibernateProperties.put(hibernate_connection_autocommit, env.getProperty(hibernate_connection_autocommit));
        hibernateProperties.put(hibernate_format_sql, env.getProperty(hibernate_format_sql));
        hibernateProperties.put(hibernate_hbm2ddl_auto, env.getProperty(hibernate_hbm2ddl_auto));
        hibernateProperties.put(hibernate_show_sql, env.getProperty(hibernate_show_sql));
//        hibernateProperties.put(hibernate_connection_provider_class, env.getProperty(hibernate_connection_provider_class));
        return hibernateProperties;

    }


    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
        HibernateTransactionManager txManager = new HibernateTransactionManager(sessionFactory);
        return txManager;
    }

这些实体是使用 Netbeans 'Entity classes from Database' 自动生成的。

主要实体有 与 FetchType.EAGER 的一对一关系 与 FetchType.EAGER 的一对多关系(这是 LAZY - 请阅读下文)。

测试方法是这样的

    @Test
    @Transactional
    public void c_testUpdateAddress1() {
        System.out.println("findById");
        String id = donorId;
        Donor donor = donorDao.findById(id);

        donor.setAbogrp(" O");

        for (DonorAddress da : donor.getDonorAddressCollection()) {
            da.setAddr1("Updated line");
            System.out.println(da.getDonorAddressPK().getAddrtype() + " " + da.getAddr1());
        }

        System.out.println("Update");

        Donor savedDonor = donorDao.save(donor);

    }    

我需要@Transactional的原因是允许地址到LAZY。
没有 @Transactional 由于异常 "failed to lazily initialize a collection of role: could not initialize proxy - no Session"

,我无法以 LAZY 身份访问地址

答案由 M Deinum 作为评论提供

符合预期。

一旦检测到 @Transactional 方法就会启动事务,并在该方法调用结束后立即提交。在测试的情况下,这是在测试方法结束之后。所以在你的测试中你不会看到 SQL。

此外,在基于 Spring 的测试中使用 @Transactional 时,默认情况下它会执行回滚而不是提交。请参阅参考指南中的 here,了解默认值以及如何更改它。