com.cvent.dropwizard.mybatis.sessionbuilder.DefaultSqlSessionFactoryProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dropwizard-mybatis Show documentation
Show all versions of dropwizard-mybatis Show documentation
An open source bridge layer so that you can use mybatis with dropwizard + other useful utility methods often used within an enterprise.
package com.cvent.dropwizard.mybatis.sessionbuilder;
import com.cvent.dropwizard.mybatis.MyBatisFactory;
import com.cvent.dropwizard.mybatis.datasource.ConfigurableLazyDataSourceFactory;
import com.cvent.pangaea.MultiEnvAware;
import io.dropwizard.db.ManagedDataSource;
import io.dropwizard.setup.Environment;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.session.SqlSessionFactory;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This is the base SqlSessionFactoryProvider class to manage SQL session initialization for all environments specified
* in the configuration on startup. It also manages new session creation during runtime for new environments not
* available in the existing session factories collection.
*
* @author Brent Ryan, Nikhil Bhagwat, zhuang
*/
public final class DefaultSqlSessionFactoryProvider implements SqlSessionFactoryProvider {
private final MultiEnvAware sessionFactories;
private final MultiEnvAware dataSourceFactories;
private final Environment dropwizardEnvironment;
private final String applicationName;
private final List> typeHandlers;
private final List> sqlMappers;
private final Map, Class>> typeClassToTypeHandlerClassMap;
private final Map> typeToAliasClassMap;
private final ObjectFactory objectFactory;
private final Map mybatisConfigurationSettings;
/**
* Create a new provider instance
*
* @param dropwizardEnvironment The dropwizard environment object
* @param applicationName The application name
* @param dataSourceFactories The MultiEnvAware datasource list used to create session factories from
* @param typeHandlers The list of type handlers to configure with each session factory
* @param sqlMappers The list of sql mappers to configure with each session factory
*/
private DefaultSqlSessionFactoryProvider(Environment dropwizardEnvironment,
String applicationName,
MultiEnvAware dataSourceFactories,
List> typeHandlers,
List> sqlMappers,
Map, Class>> typeClassToTypeHandlerClassMap,
Map> typeToAliasClassMap,
ObjectFactory objectFactory,
Map mybatisConfigurationSettingsMap) {
this.dropwizardEnvironment = dropwizardEnvironment;
this.applicationName = applicationName;
this.dataSourceFactories = dataSourceFactories;
this.typeHandlers = typeHandlers;
this.sqlMappers = sqlMappers;
this.typeClassToTypeHandlerClassMap = typeClassToTypeHandlerClassMap;
this.typeToAliasClassMap = typeToAliasClassMap;
this.objectFactory = objectFactory;
this.mybatisConfigurationSettings = mybatisConfigurationSettingsMap;
sessionFactories = dataSourceFactories.convert((env, dataSource) -> buildSessionFactory(dataSource, env));
}
/**
* A simple builder allowing us to customize the underlying session factory provider
*/
public static class Builder {
private final List> typeHandlers = new ArrayList<>();
private final List> sqlMappers = new ArrayList<>();
private final Map, Class>> typeClassToTypeHandlerClassMap = new HashMap<>();
private final Map> typeToAliasClassMap = new HashMap<>();
private final MultiEnvAware dataSourceFactories;
private final Environment dropwizardEnvironment;
private final String applicationName;
private ObjectFactory objectFactory;
private final Map mybatisConfigurationSettingsMap = new HashMap<>();
/**
* A new Builder
*
* @param dropwizardEnvironment The dropwizard environment object
* @param applicationName The application name
* @param dataSourceFactories The MultiEnvAware datasource list used to create session factories from
*/
public Builder(Environment dropwizardEnvironment, String applicationName,
MultiEnvAware dataSourceFactories) {
this.dropwizardEnvironment = dropwizardEnvironment;
this.applicationName = applicationName;
this.dataSourceFactories = dataSourceFactories;
}
/**
* Register a new type handler to be used with this sql session provider
*
* @param typeHandler
* @return
*/
public Builder register(Class> typeHandler) {
typeHandlers.add(typeHandler);
return this;
}
/**
* Register a new type and type handler association to be used with this sql session provider
*
* @param javaTypeClass
* @param typeHandlerClass
* @return
*/
public Builder register(Class> javaTypeClass, Class> typeHandlerClass) {
typeClassToTypeHandlerClassMap.put(javaTypeClass, typeHandlerClass);
return this;
}
/**
* Register a new alias to be used with this sql session provider
*
* @param alias
* @param value
* @return
*/
public Builder registerAlias(String alias, Class> value) {
typeToAliasClassMap.put(alias, value);
return this;
}
/**
* Register a new sql mapper to be used with this sql session provider
*
* @param sqlMapper
* @return
*/
public Builder addMapper(Class> sqlMapper) {
sqlMappers.add(sqlMapper);
return this;
}
/**
* Add an object factory to the builder
*
* @param factory
* @return
*/
public Builder objectFactory(ObjectFactory factory) {
this.objectFactory = factory;
return this;
}
/**
* Add a new MyBatis Configuration Setting.
* @param configName
* @param configSettingObject
* @return
*/
public Builder addConfigurationSettings(String configName, Object configSettingObject) {
this.mybatisConfigurationSettingsMap.put(configName, configSettingObject);
return this;
}
/**
* Create a new SqlSessionFactoryProvider based on the attributes that have been added to this builder
*
* @return a new instance of SqlSessionFactoryProvider
*/
public SqlSessionFactoryProvider build() {
return new DefaultSqlSessionFactoryProvider(dropwizardEnvironment,
applicationName,
dataSourceFactories,
typeHandlers,
sqlMappers,
typeClassToTypeHandlerClassMap,
typeToAliasClassMap,
objectFactory,
mybatisConfigurationSettingsMap);
}
}
/**
* Build a new sql session factory. This method is NOT threadsafe so this internal class must take care to
* synchronize on sessionFactories.
*
* @param dataSource The datasource to use for constructing the session factory from
* @param environmentName The environment name to use
* @return A new SqlSessionFactory
*/
private SqlSessionFactory buildSessionFactory(ConfigurableLazyDataSourceFactory dataSource,
String environmentName) {
String dataSourceName = String.format("%s-%s-sql", applicationName, environmentName);
ManagedDataSource ds = dataSource.build(dropwizardEnvironment.metrics(), dataSourceName);
SqlSessionFactory sessionFactory = new MyBatisFactory()
.build(dropwizardEnvironment, dataSource, ds, dataSourceName);
for (Map.Entry, Class>> typeClassToTypeHandlerClassEntry :
typeClassToTypeHandlerClassMap.entrySet()) {
sessionFactory.getConfiguration().getTypeHandlerRegistry().register(
typeClassToTypeHandlerClassEntry.getKey(),
typeClassToTypeHandlerClassEntry.getValue());
}
for (Map.Entry> typeToAliasClassEntry :
typeToAliasClassMap.entrySet()) {
sessionFactory.getConfiguration().getTypeAliasRegistry().registerAlias(
typeToAliasClassEntry.getKey(),
typeToAliasClassEntry.getValue());
}
for (Class> typeHandler : typeHandlers) {
sessionFactory.getConfiguration().getTypeHandlerRegistry().register(typeHandler);
}
for (Class> sqlMapper : sqlMappers) {
sessionFactory.getConfiguration().addMapper(sqlMapper);
}
if (objectFactory != null) {
sessionFactory.getConfiguration().setObjectFactory(objectFactory);
}
mybatisConfigurationSettings.forEach((settingName, configSettingObject) -> {
try {
Field field = sessionFactory.getConfiguration().getClass().getDeclaredField(settingName);
field.setAccessible(true);
field.set(sessionFactory.getConfiguration(), configSettingObject);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
});
//Only add to it after it's be initialized. This is used mainly for "templates"
if (sessionFactories != null) {
sessionFactories.put(environmentName, sessionFactory);
}
return sessionFactory;
}
/**
* Get SQL session by environment name, create a new session if requested environment is not found
*
* @param environmentName
* @return SqlSessionFactory
*/
@Override
public SqlSessionFactory getSqlSessionFactory(String environmentName) {
if (StringUtils.isBlank(environmentName) || sessionFactories.containsKey(environmentName)) {
return sessionFactories.get(environmentName);
}
//implement double check locking so that we're protected against multiple threads trying to get a session
//factory while avoiding the possibility of duplication session factories and not hurting performance for 99% of
//the calls.
synchronized (this) {
if (StringUtils.isBlank(environmentName) || sessionFactories.containsKey(environmentName)) {
return sessionFactories.get(environmentName);
} else {
return buildSessionFactory(dataSourceFactories.get(environmentName), environmentName);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy