Intercepting your querys with SpringBoot and Hibernate

Intercepting your querys with SpringBoot and Hibernate

Intercepting querys

Recently appear for me a old problem: replace schema of one database in runtime.

I provide one solution in the past, but now, the architecture is little bit different, using SpringBoot.

The class is big, but the important parts will be commented. So let's go code:

@Configuration
@EnableTransactionManagement
@ConditionalOnExpression("${spring.jta.enabled}==false")
@EnableJpaRepositories(basePackages = "my.package.fqn",
entityManagerFactoryRef = "anyNameEntityManagerFactory",
transactionManagerRef = "anyNameTransactionManager",
repositoryImplementationPostfix = "Impl")
public class DatabaseConfigurationAnyName {

   @Bean(destroyMethod = "")
   public DataSource sbaDataSource() {
       String jni = env.getProperty("spring.name.jndi_name");
       if (jni == null) {
          DataSourceProperties dsp = new DataSourceProperties();
          dsp.setUrl(env.getProperty("spring.name.datasource.url"));
          dsp.setUsername(env.getProperty("spring.name.datasource.username"));
          dsp.setPassword(env.getProperty("spring.name.datasource.password"));
          dsp.setDriverClassName(env.getProperty("spring.name.datasource.driver-class-name"));
          final DataSource ds = dsp.initializeDataSourceBuilder()
             .type(HikariDataSource.class)
             .build();
         return ds;
      }

      final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
      dsLookup.setResourceRef(true);
      DataSource dataSource = dsLookup.getDataSource(jni);
      return dataSource;
   }

   @Bean(name = "anyNameEntityManagerFactory")
   public LocalContainerEntityManagerFactoryBean anyNameEntityManagerFactory() {

      LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
      em.setDataSource(sbaDataSource());
      em.setPackagesToScan(
      new String[] {
          "my.package.name"
      });

     HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
     em.setJpaVendorAdapter(vendorAdapter);
     HashMap<String, Object> properties = new HashMap<>();
     properties.put("hibernate.dialect", env.getProperty("spring.sba.hibernate.dialect"));
     properties.put("hibernate.physical_naming_strategy",   env.getProperty("spring.sba.hibernate.physical_naming_strategy"));
properties.put("hibernate.format_sql",env.getProperty("spring.sba.hibernate.format_sql"));
    properties.put("hibernate.show_sql", env.getProperty("spring.sba.hibernate.show_sql"));
    properties.put("hibernate.dualhbm2ddl.auto", true);
    properties.put("hibernate.default_schema", env.getProperty("spring.sba.hibernate.default_schema"));
    properties.put("hibernate.default_catalog", env.getProperty("spring.sba.hibernate.default_catalog"));
    properties.put("hibernate.id.new_generator_mappings", env.getProperty("spring.sba.hibernate.id.new_generator_mappings"));
    // Adding the method
    properties.put("hibernate.ejb.interceptor", interceptorSQL());

    em.setJpaPropertyMap(properties);

    return em;
  }

  @Bean
   public PlatformTransactionManager anyNameTransactionManager(
      final @Qualifier("anyNameEntityManagerFactory")      LocalContainerEntityManagerFactoryBean memberEntityManagerFactory) {
      return new JpaTransactionManager(memberEntityManagerFactory.getObject());
    }

   // The method that do the replace
   @Bean
   public EmptyInterceptor interceptorSQL() {
       return new EmptyInterceptor() {
           @Override
           public String onPrepareStatement(String sql) {
               sql = sql.replaceAll("argument", "value");
               return super.onPrepareStatement(sql);
           }
        };
  }
}

and that’s all folks!

If you have any doubts, problems or suggestions, just leave a message.