Hibernate/JPA如何保證不生成多餘的SQL語句?
對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 public class DatasourceProxyBeanPostProcessor implements BeanPostProcessor { private static final Logger logger = Logger.getLogger(DatasourceProxyBeanPostProcessor.class.getName()); @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof DataSource) { logger.info(() -> "DataSource bean has been found: " + bean); final ProxyFactory proxyFactory = new ProxyFactory(bean); proxyFactory.setProxyTargetClass(true); proxyFactory.addAdvice(new ProxyDataSourceInterceptor((DataSource) bean)); return proxyFactory.getProxy(); } return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } private static class ProxyDataSourceInterceptor implements MethodInterceptor { private final DataSource dataSource; public ProxyDataSourceInterceptor(final DataSource dataSource) { super(); this.dataSource = ProxyDataSourceBuilder.create(dataSource) .name("DATA_SOURCE_PROXY") .logQueryBySlf4j(SLF4JLogLevel.INFO) .multiline() .countQuery() .build(); } @Override public Object invoke(final MethodInvocation invocation) throws Throwable { final Method proxyMethod = ReflectionUtils. findMethod(this.dataSource.getClass(), invocation.getMethod().getName()); if (proxyMethod != null) { return proxyMethod.invoke(this.dataSource, invocation.getArguments()); } return invocation.proceed(); } } } |
第三步:透過SQLStatementCountValidator.reset()重置計數器:
@SpringBootApplication public class CountSQLStatementsApplication { @Autowired private UserService userService; public static void main(String args) { SpringApplication.run(CountSQLStatementsApplication.class, args); } @Bean public ApplicationRunner init() { return args -> { userService.userOperationsWithoutTransactional(); SQLStatementCountValidator.reset(); userService.userOperationsWithTransactional(); // allow the transaction to commit // a total of 2 statements instead of 5 as in the case of no explicit transaction assertInsertCount(1); assertUpdateCount(0); assertDeleteCount(1); assertSelectCount(0); }; } } |
第四步:透過assertInsert{Update/ Delete/Select}Count(long expectedNumberOfSql斷言INSERT,UPDATE,DELETE,和SELECT:
@Service public class UserService { @Autowired private UserRepository userRepository; public void userOperationsWithoutTransactional() { User user = new User(); user.setName("Jacky Francisco"); user.setCity("Banesti"); user.setAge(24); SQLStatementCountValidator.reset(); userRepository.save(user); // 1 insert user.setCity("Craiova"); userRepository.save(user); // 1 update userRepository.delete(user); // 1 delete // at this point there is no transaction running // a total of 5 statements, not very good assertInsertCount(1); assertUpdateCount(1); assertDeleteCount(1); assertSelectCount(2); } @Transactional public void userOperationsWithTransactional() { User user = new User(); user.setName("Jacky Francisco"); user.setCity("Banesti"); user.setAge(24); userRepository.save(user); // 1 insert user.setCity("Craiova"); userRepository.save(user); // update not triggered since a delete follows userRepository.delete(user); // 1 delete } } |
原始碼可以在這裡找到
相關文章
- Java中如何解析SQL語句、格式化SQL語句、生成SQL語句?JavaSQL
- hibernate在JPA規範中在控制檯無法出現SQL語句SQL
- Hibernate/JPA中避免save()冗餘呼叫
- 如何透過Hibernate/JPA的SqlResultSetMapping生成需要資料的DTO?SQLAPP
- jsqlparser使用記錄---生成sql語句JSSQL
- sql語句如何執行的SQL
- 定時生成分月表sql語句SQL
- EFCore常規操作生成的SQL語句一覽SQL
- 如何在SpringBoot中使用Hibernate/JPA的@NaturalId?Spring Boot
- JPA與hibernate-------JPA01
- IDEA如何快速複製日誌生成sql語句,太妙啦IdeaSQL
- 如何使用Hibernate/JPA的JPQL/HQL查詢提取?
- excel表結構生成powerDesigner模型,生成建表語句sqlExcel模型SQL
- SQL語句SQL
- SQL語句IN的用法SQL
- Hibernate/JPA中如何合併實體集合?
- [20220331]如何調整sql語句.txtSQL
- 【SQL】9 SQL INSERT INTO 語句SQL
- 【SQL】10 SQL UPDATE 語句SQL
- 【SQL】11 SQL DELETE 語句SQLdelete
- 自定義註解例項實現SQL語句生成SQL
- SQL SELECT 語句SQL
- sql常用語句SQL
- DBeaver如何生成select,update,delete,insert語句delete
- 一條update SQL語句是如何執行的SQL
- 一條SQL更新語句是如何執行的SQL
- 一條SQL更新語句是如何執行的?SQL
- 一條更新的SQL語句是如何執行的?SQL
- Hibernate/JPA中@OneToOne和@MapsId的使用
- 淺談JPA二:聊聊Hibernate
- 基於 SQL 解析的 JPA 多租戶方案SQL
- MySQL中常用的SQL語句MySql
- sqlserver dba常用的sql語句SQLServer
- SQL 語句的注意事項SQL
- sql宣告變數,及if -else語句、while語句的用法SQL變數While
- 1.3. SQL 語句SQL
- Oracle基本SQL語句OracleSQL
- Sql語句小整理SQL