内容简介:对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语句?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- roncoo-recharge 1.0.0 正式版发布,去除多余的模块
- MySQL 建表语句转 PostgreSQL 建表语句全纪录
- Go语言开发-过程式编程-通信和并发语句-Select语句
- SQL语句优化之JOIN和LEFT JOIN 和 RIGHT JOIN语句的优化
- Python 条件语句
- Python 循环语句
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML5+CSS3精致范例辞典
杨东昱 / 清华大学出版社 / 2013-1 / 48.00元
《HTML5+CSS3精致范例辞典(全彩印刷)》是专为希望成为网页设计师的学习者打造的工具书,书中详细说明了设计网页所需的HTML标记语言,对HTML5的网页标签规范作了完整说明,如元素标签的功能、属性以及如何使用等。有了基本网页制作能力,如何让网页更出色,版面更富变化、更易维护管理,那就得靠CSS帮忙了。《HTML5+CSS3精致范例辞典(全彩印刷)》还详细解说了最新CSS3的样式元素,除了说明......一起来看看 《HTML5+CSS3精致范例辞典》 这本书的介绍吧!