当前位置: 首页 > 知识库问答 >
问题:

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

闻人高卓
2023-03-14
  • Spring V4.2.5发行版
  • Hibernate V5.1.0.final

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

在方法签名中添加@transactional会阻止执行更新SQL(日志中没有生成SQL)。

删除@transaction,将生成更新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的实体类从数据库自动生成的。

主实体与FetchType.Eager有一对一的关系,与FetchType.Eager有一对多的关系(它是懒惰的-阅读下面)。

测试方法看起来是这样的。

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

    }    

>

  • 不使用@transaction将生成更新SQL,并更新数据库。
  • 使用@transactional时,不会生成更新SQL,也不会出现在日志中。没有例外,在我的Dao实现中跳过Save方法,一切似乎都很好。传入的bean具有正确的值(更新的字段值),返回的bean具有更新的字段值-只是没有生成SQL。

    @Override
    public Donor save(Donor bean) {
    
        getSession().saveOrUpdate(bean);
        return bean;
    }
    

    我需要@transactional的原因是允许该地址为懒惰的。
    如果没有@transaction,我不能以懒惰的身份访问该地址,因为异常“未能懒惰地初始化角色集合:无法初始化代理-没有会话”

  • 共有1个答案

    姜良哲
    2023-03-14

    不出所料。

    一旦检测到@transactional方法,事务就会启动,一旦该方法调用结束,事务就会提交。在测试的情况下是在测试方法结束之后。因此,在测试期间,您将看不到SQL。

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

     类似资料:
    • 问题内容: 保存hibernate对象时,hibernate中是否有设置可以 忽略 属性的 空值 ? 注意 在我的情况下,我正在通过杰克逊将JSON反序列化为Hibernate Pojo。 JSON仅包含Pojo的某些字段。如果保存Pojo,则不在JSON中的字段在Pojo中为null,然后hibernate更新它们。 我遇到了这个问题,但这不是100%的解决方案。 http://docs.jbo

    • 本文向大家介绍JS打开新窗口防止被浏览器阻止的方法,包括了JS打开新窗口防止被浏览器阻止的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JS打开新窗口防止被浏览器阻止的方法。分享给大家供大家参考。具体分析如下: 用传统的window.open()方式打开新窗口,会被浏览器阻止,那么,我们如何才能让JS打开新窗口不被浏览器阻止呢?其实办法还是有的,这里我们就来分析一下如何解决这个问题

    • 问题内容: 我有一个对话框,其中JTree中的每个条目在不同的面板中都有其相应的选项,当选择更改时会更新该面板。如果将其中一项的选项设置为无效状态,则当用户尝试更改树中的其他项时,我希望出现一个错误对话框,并且选择保持不变。 我尝试使用JTree上的valueChangeListener来执行此操作,但是目前如果有错误,则必须让valueChanged方法将“ setSelectionRow”调用

    • 我重新启动服务器和浏览器,因此没有会话数据 我去www.someurl。com公共访问页。我的控制器用这个HttpSession session=request给我一个会话。getSession(true) <李> 我点击一个指向www.someurl的平面锚链接。在新选项卡中打开的com/admin受限访问页面。Spring Security 3拦截了这一点,并对凭据提出了挑战。我成功登录 我返

    • 但我又被1175错误阻塞了。 为什么安全更新模式在这里阻止我?我可以在不禁用安全更新模式的情况下解决它吗?

    • com.mysql.jdbc.exceptions.jdbc4.mysqlintegrityConstraintViolationException:无法添加或更新子行:外键约束失败(.,constraint外键()引用()