J'ai besoin de définir certaines propriétés de connexion Oracle JDBC spécifiques afin d'accélérer le lot INSERT
s (defaultBatchValue
) et la masse SELECT
s (defaultRowPrefetch
). J'ai suggestions comment y parvenir avec DBCP (Merci à M. Deinum) mais je voudrais:
Je pensais à une demande de fonctionnalité pour prendre en charge spring.datasource.custom_connection_properties
ou similaire à l'avenir et à cause de cela a essayé de prétendre que c'était déjà possible. J'ai fait cela en transmettant les informations pertinentes lors de la création de la DataSource et en manipulant la création de la DataSource comme ceci:
@Bean
public DataSource dataSource() {
DataSource ds = null;
try {
Field props = DataSourceBuilder.class.getDeclaredField("properties");
props.setAccessible(true);
DataSourceBuilder builder = DataSourceBuilder.create();
Map<String, String> properties = (Map<String, String>) props.get(builder);
properties.put("defaultRowPrefetch", "1000");
properties.put("defaultBatchValue", "1000");
ds = builder.url( "jdbc:Oracle:thin:@xyz:1521:abc" ).username( "ihave" ).password( "wonttell" ).build();
properties = (Map<String, String>) props.get(builder);
log.debug("properties after: {}", properties);
} ... leaving out the catches ...
}
log.debug("We are using this datasource: {}", ds);
return ds;
}
Dans les journaux, je peux voir que je crée la bonne source de données:
2016-01-18 14:40:32.924 DEBUG 31204 --- [ main] d.a.e.a.c.config.DatabaseConfiguration : We are using this datasource: org.Apache.Tomcat.jdbc.pool.DataSource@19f040ba{ConnectionPool[defaultAutoCommit=null; ...
2016-01-18 14:40:32.919 DEBUG 31204 --- [ main] d.a.e.a.c.config.DatabaseConfiguration : properties after: {password=wonttell, driverClassName=Oracle.jdbc.OracleDriver, defaultRowPrefetch=1000, defaultBatchValue=1000, url=jdbc:Oracle:thin:@xyz:1521:abc, username=ihave}
L'actionneur me montre que mon code a remplacé la source de données:
Mais les paramètres ne sont pas activés, ce que je peux voir lors du profilage de l'application. defaultRowPrefetch
est toujours à 10
ce qui fait que mes SELECT
s sont beaucoup plus lents qu'ils ne le seraient si 1000
a été activé.
La définition des pools connectionProperties devrait fonctionner. Ceux-ci seront transmis au pilote JDBC. Ajoutez ceci à application.properties:
spring.datasource.connectionProperties: defaultRowPrefetch=1000;defaultBatchValue=1000
Modifier (quelques informations générales):
Notez également que vous pouvez configurer n'importe quelle propriété spécifique de l'implémentation de DataSource via spring.datasource. *: Reportez-vous à la documentation de l'implémentation du pool de connexions que vous utilisez pour plus de détails.
source: documentation Spring-boot
Comme Spring Boot est EOL depuis longtemps, je suis passé à Spring Boot 2.1 avec son nouveau pool de connexions par défaut Hikari. Ici, la solution est encore plus simple et peut être effectuée dans le fichier application.properties ou (comme illustré ici) application.yml:
spring:
datasource:
hikari:
data-source-properties:
defaultRowPrefetch: 1000
(Dans une configuration réelle, il y aurait plusieurs autres éléments de configuration mais comme ils ne sont pas intéressants pour la question posée, je les ai simplement laissés de côté dans mon exemple)
Quelques informations supplémentaires pour compléter la réponse de @Cyril. Si vous voulez voter, utilisez sa réponse, pas la mienne.
J'étais un peu perplexe à quel point il est facile de définir des propriétés de connexion supplémentaires qui finalement seront utilisées lors de la création de la connexion à la base de données. J'ai donc fait un peu de recherche.
spring.datasource.connectionProperties
n'est pas mentionné dans le référence . J'ai créé un problème à cause de cela. Si j'avais utilisé éditeur Spring Boot YML , j'aurais vu quelles propriétés sont prises en charge. Voici ce que STS suggère lorsque vous créez un application.yml
et appuyez sur Ctrl+Space:
Le tiret n'a pas d'importance à cause de liaison relâchée mais si vous l'interprétez littéralement, le nom de la propriété est spring.datasource.connection-properties
.
La configuration correcte dans application.yml ressemble à ceci:
spring:
datasource:
connection-properties: defaultBatchValue=1000;defaultRowPrefetch=1000
...
Cela est honoré, ce qui est prouvé par mes mesures perf4j de masse SELECT
s.
Avant:
2016-01-19 08: 58: 32.604 INFO 15108 --- [principal] org.perf4j.TimingLogger: start [1453190311227] time [1377] tag [get elements]
Après:
2016-01-19 08: 09: 18.214 INFO 9152 --- [principal] org.perf4j.TimingLogger: start [1453187358066] time [147] tag [get elements]
Le temps nécessaire pour terminer l'instruction SQL passe de 1377 ms à 147, ce qui représente un énorme gain de performances.
Après avoir fouillé un peu dans le code Tomcat, j'ai trouvé que la dataSource.getPoolProperties().getDbProperties()
est l'objet Properties
qui sera réellement utilisé pour générer des connexions pour le pool.
Si vous utilisez l'approche BeanPostProcessor
mentionnée par @ m-deinum, mais que vous l'utilisez à la place pour remplir les dbProperties
comme cela, vous devriez pouvoir ajouter les propriétés d'une manière qui les rend collantes et être transmis au pilote Oracle.
import Java.util.Properties;
import org.Apache.Tomcat.jdbc.pool.DataSource;
import org.Apache.Tomcat.jdbc.pool.PoolConfiguration;
@Component
public class OracleConfigurer implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
if (bean instanceof DataSource) {
DataSource dataSource = (DataSource)bean;
PoolConfiguration configuration = dataSource.getPoolProperties();
Properties properties = configuration.getDbProperties();
if (null == properties) properties = new Properties();
properties.put("defaultRowPrefetch", 1000);
properties.put("defaultBatchValue", 1000);
configuration.setDbProperties(properties);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
return bean;
}
}