Hibernate/JPA如何保证不生成多余的SQL语句?

栏目: Hibernate · 发布时间: 7年前

内容简介:对SQL语句如果没有计数和断言的情况下,很容易失去对当前场景背后执行的SQL的控制,从而导致性能损失。本应用是计数和断言“幕后”触发的SQL语句的示例。计数SQL语句非常有用,以确保您的代码不会生成比你预计的更多的SQL(例如,通过声明预期语句的数量可以轻松检测到N + 1)。第一步:在Maven的pom.xml中添加依赖datasource-proxy和Vlad Mihalcea的db-util:

SQL 语句如果没有计数和断言的情况下,很容易失去对当前场景背后执行的SQL的控制,从而导致性能损失。

本应用是计数和断言“幕后”触发的SQL语句的示例。计数SQL语句非常有用,以确保您的代码不会生成比你预计的更多的SQL(例如,通过声明预期语句的数量可以轻松检测到N + 1)。

第一步:在Maven的pom.xml中添加依赖datasource-proxy和Vlad Mihalcea的db-util:

 <dependency>
            <groupId>net.ttddyy</groupId>
            <artifactId>datasource-proxy</artifactId>
            <version>${datasource-proxy.version}</version>
        </dependency>
        <dependency>
            <groupId>com.vladmihalcea</groupId>
            <artifactId>db-util</artifactId>
            <version>${db-util.version}</version>
        </dependency>

第二步:使用countQuery()创建ProxyDataSourceBuilder:

@Component
<b>public</b> <b>class</b> DatasourceProxyBeanPostProcessor implements BeanPostProcessor {

    <b>private</b> <b>static</b> <b>final</b> Logger logger
            = Logger.getLogger(DatasourceProxyBeanPostProcessor.<b>class</b>.getName());

    @Override
    <b>public</b> Object postProcessAfterInitialization(Object bean, String beanName) {

        <b>if</b> (bean instanceof DataSource) {

            logger.info(() -> <font>"DataSource bean has been found: "</font><font> + bean);

            <b>final</b> ProxyFactory proxyFactory = <b>new</b> ProxyFactory(bean);

            proxyFactory.setProxyTargetClass(<b>true</b>);
            proxyFactory.addAdvice(<b>new</b> ProxyDataSourceInterceptor((DataSource) bean));

            <b>return</b> proxyFactory.getProxy();
        }
        <b>return</b> bean;
    }

    @Override
    <b>public</b> Object postProcessBeforeInitialization(Object bean, String beanName) {
        <b>return</b> bean;
    }

    <b>private</b> <b>static</b> <b>class</b> ProxyDataSourceInterceptor implements MethodInterceptor {

        <b>private</b> <b>final</b> DataSource dataSource;

        <b>public</b> ProxyDataSourceInterceptor(<b>final</b> DataSource dataSource) {
            <b>super</b>();
            <b>this</b>.dataSource = ProxyDataSourceBuilder.create(dataSource)
                    .name(</font><font>"DATA_SOURCE_PROXY"</font><font>)
                    .logQueryBySlf4j(SLF4JLogLevel.INFO)
                    .multiline()
                    .countQuery()
                    .build();
        }

        @Override
        <b>public</b> Object invoke(<b>final</b> MethodInvocation invocation) throws Throwable {

            <b>final</b> Method proxyMethod = ReflectionUtils.
                    findMethod(<b>this</b>.dataSource.getClass(),
                            invocation.getMethod().getName());

            <b>if</b> (proxyMethod != <b>null</b>) {
                <b>return</b> proxyMethod.invoke(<b>this</b>.dataSource, invocation.getArguments());
            }

            <b>return</b> invocation.proceed();
        }
    }
}
</font>

第三步:通过SQLStatementCountValidator.reset()重置计数器:

@SpringBootApplication
<b>public</b> <b>class</b> CountSQLStatementsApplication {

    @Autowired
    <b>private</b> UserService userService;

    <b>public</b> <b>static</b> <b>void</b> main(String args) {
        SpringApplication.run(CountSQLStatementsApplication.<b>class</b>, args);
    }

    @Bean
    <b>public</b> ApplicationRunner init() {
        <b>return</b> args -> {

            userService.userOperationsWithoutTransactional();
            
            SQLStatementCountValidator.reset();      
            userService.userOperationsWithTransactional();

            <font><i>// allow the transaction to commit</i></font><font>
            </font><font><i>// a total of 2 statements instead of 5 as in the case of no explicit transaction</i></font><font>
            assertInsertCount(1);
            assertUpdateCount(0);
            assertDeleteCount(1);
            assertSelectCount(0);
        };
    }
}
</font>

第四步:通过assertInsert{Update/ Delete/Select}Count(long expectedNumberOfSql断言INSERT,UPDATE,DELETE,和SELECT:

@Service
<b>public</b> <b>class</b> UserService {

    @Autowired
    <b>private</b> UserRepository userRepository;

    <b>public</b> <b>void</b> userOperationsWithoutTransactional() {
        User user = <b>new</b> User();

        user.setName(<font>"Jacky Francisco"</font><font>);
        user.setCity(</font><font>"Banesti"</font><font>);
        user.setAge(24);

        SQLStatementCountValidator.reset();

        userRepository.save(user);   </font><font><i>// 1 insert</i></font><font>
        user.setCity(</font><font>"Craiova"</font><font>);
        userRepository.save(user);   </font><font><i>// 1 update</i></font><font>
        userRepository.delete(user); </font><font><i>// 1 delete</i></font><font>

        </font><font><i>// at this point there is no transaction running</i></font><font>
        </font><font><i>// a total of 5 statements, not very good</i></font><font>
        assertInsertCount(1);
        assertUpdateCount(1);
        assertDeleteCount(1);
        assertSelectCount(2);
    }

    @Transactional
    <b>public</b> <b>void</b> userOperationsWithTransactional() {
        User user = <b>new</b> User();

        user.setName(</font><font>"Jacky Francisco"</font><font>);
        user.setCity(</font><font>"Banesti"</font><font>);
        user.setAge(24);
              
        userRepository.save(user);   </font><font><i>// 1 insert</i></font><font>
        user.setCity(</font><font>"Craiova"</font><font>);
        userRepository.save(user);   </font><font><i>// update not triggered since a delete follows</i></font><font>
        userRepository.delete(user); </font><font><i>// 1 delete        </i></font><font>
    }
}
</font>

源代码可以在 这里 找到


以上所述就是小编给大家介绍的《Hibernate/JPA如何保证不生成多余的SQL语句?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Implementing Responsive Design

Implementing Responsive Design

Tim Kadlec / New Riders / 2012-7-31 / GBP 27.99

New devices and platforms emerge daily. Browsers iterate at a remarkable pace. Faced with this volatile landscape we can either struggle for control or we can embrace the inherent flexibility of the w......一起来看看 《Implementing Responsive Design》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具