Ho eseguito alcuni test delle prestazioni per confrontare la parzializzazione sovraccarico/prestazioni tra querydsl e jdbctemplate.
Ecco che cosa ho fatto
1. Creato un progetto di avvio molla che utilizza querydsl e jdbctemplate
2. Creato 2 punti finali, 1 per l'utilizzo di querydsl e un altro per jdbctemplate.
3. La configurazione di querydsl utilizza l'origine dati autofigurata di avvio di primavera per configurare SQLQueryFactory.
4. JdbcTemplate viene inoltre configurato automaticamente con la stessa origine dati autoconfigurata.
5. Ci sono 2 implementazioni di una query simile nel repository, una usa querydsl e l'altra usa jdbctemplate. La query è relativamente complessa e consiste in un paio di join interni e clausole in cui.
6. I metodi di servizio hanno un ciclo for e chiama il metodo repository in ogni iterazione. No. di iterazioni è configurabile ed è stato impostato su 1 ciclo di iterazioni.
7. System.nanoTime() viene utilizzato attorno al metodo di servizio nel controller per calcolare il tempo impiegato per eseguire le numerose iterazioni del metodo di repository.
8. JdbcTemplate ha impiegato una media di 800 ms per eseguire 1 chiamate lakh di repository.
9. Querydsl ha impiegato una media di 5000 ms per eseguire 1 chiamate lakh di repository.
10. Osservazione: Querydsl è 6 volte più lento di JdbcTemplate per la stessa query. Il sovraccarico è presumibilmente nella serializzazione della query di querydsl.
QueryDSL Attuazione Repository
List<Customer> customers = new ArrayList<>();
Customer customerObj = null;
List<Tuple> customerTuples =queryFactory.select(customer.firstName,customer.status,customer.customerId).
from(customer).innerJoin(customerChat).on(customer.customerId.eq(customerChat.senderId)).
innerJoin(customerChatDetail).on(customerChat.chatDetailId.eq(customerChatDetail.chatDetailId)).
where(customerChatDetail.isRead.eq(true).and(customer.status.eq(true))).fetch();
for (Tuple row : customerTuples) {
customerObj = new Customer();
customerObj.setFirstName(row.get(customer.firstName));
customerObj.setStatus(row.get(customer.status));
customerObj.setCustomerId(row.get(customer.customerId));
customers.add(customerObj);
}
return customers;
JdbcTemplate Attuazione
List<Customer> customers = this.jdbcTemplate.query(
"select first_name,status,customer_id from customer inner join v_customer_chat on customer.customer_id=v_customer_chat.sender_id inner join v_customer_chat_detail on v_customer_chat.chat_detail_id = v_customer_chat_detail.chat_detail_id where v_customer_chat_detail.is_read = ? and customer.status = ?;",new Object[] {true, true},
new RowMapper<Customer>() {
public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
Customer customer = new Customer();
customer.setFirstName(rs.getString("first_name"));
customer.setStatus(rs.getBoolean("status"));
customer.setCustomerId(rs.getLong("customer_id"));
return customer;
}
});
Fondamentalmente sto cercando di fare la stessa cosa con diverse librerie e misura che uno incorre più in alto.
1. Eseguire una query relativamente complessa con join.
2. Popolare i bean dal set di risultati.
Sto utilizzando il database in memoria H2. Il database contiene solo un paio di record per ogni tabella. E 1 riga di risultati che corrisponde alla query.
Il metodo viene eseguito in un ciclo for (1 ciclo di iterazioni). E tempo calcolato con l'aiuto di System.nanoTime() attorno al ciclo.
È un progetto di avvio a molla con diversi endpoint (uno per querydsl e un altro per jdbctemplate). La configurazione per querydsl e queryfactory viene eseguita come segue
@Autowired
public DataSource dataSource;
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public com.querydsl.sql.Configuration querydslConfiguration() {
SQLTemplates templates = H2Templates.builder().build();
com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates);
configuration.setExceptionTranslator(new SpringExceptionTranslator());
return configuration;
}
@Bean
public SQLQueryFactory queryFactory() {
Provider<Connection> provider = new SpringConnectionProvider(dataSource);
return new SQLQueryFactory(querydslConfiguration(), provider);
}
Un po 'come _ "Assembler (o C) è più veloce." _ Non riuscirai mai a convincerli pro QueryDSL a meno che non ci siano casi d'uso che traggano vantaggio dall'intelligenza incorporata. Così fai qualche riscrittura, forse troverai alcune cose: errori in SQL, notazione breve, ottimizzazioni in QueryDSL, SQL risultante. –
Capisco che si tratti di compromessi tra prestazioni non elaborate e compatibilità degli sviluppatori (manutenibilità). Quello che voglio dimostrare (o mi aspetto) è che QueryDSL SQL fornisce prestazioni notevolmente migliori rispetto a JPA/ORM ed è solo "leggermente" sovraperformato da JDBCTemplate. Sono alla ricerca di alcuni fatti/figure per questo. Nel frattempo, sto provando anche io alcune prove. –