一,添加依赖
添加presto和mysql的依赖
<dependency> <groupId>com.facebook.presto</groupId> <artifactId>presto-jdbc</artifactId> <version>0.203</version> </dependency>
mysql的依赖就不贴了。
二,application.properties文件

三,多数据源配置
/**
* aop数据源切换
* 自定义注解dataSource 默认数据源为mysql, @DataSource(PRESTO_DATA_SOURCE)在mapper接口加上此注解为presto
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface DataSource {
String value() default DataSourceConstants.DEFAULT_DATA_SOURCE;
}
@Configuration
public class DataSourceConfig {
Logger log = Logger.getLogger("dataSourceConfig");
@Autowired
private DruidConfiguration defaultDataSource;
@Autowired(required = false)
private Interceptor[] interceptors;
//presto数据源
@Bean(name = DataSourceConstants.PRESTO_DATA_SOURCE)
@ConfigurationProperties(prefix = "presto.spring.datasource.marketing")
public DataSource prestoDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 动态数据源: 通过AOP在不同数据源之间动态切换
*
* @return
*/
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认数据源
dynamicDataSource.setDefaultTargetDataSource(defaultDataSource.dataSource());
// 配置多数据源
Map<Object, Object> dsMap = new HashMap<>();
dsMap.put(DataSourceConstants.DEFAULT_DATA_SOURCE, defaultDataSource.dataSource());
dsMap.put(DataSourceConstants.PRESTO_DATA_SOURCE, prestoDataSource());
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
@Bean
public SqlSessionFactoryBean sessionFactoryBean(
@Value("${mybatis.mapper-locations}") String mapperLocations,
@Value("${mybatis.configuration.map-underscore-to-camel-case}") boolean mapUnderscoreToCamelCase) throws IOException {
System.out.println("mapperLocations--------->" + mapperLocations);
System.out.println("map-underscore-to-camel-case--------->" + mapUnderscoreToCamelCase);
log.info("mapperLocations--------->" + mapperLocations);
log.info("map-underscore-to-camel-case--------->" + mapUnderscoreToCamelCase);
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(mapUnderscoreToCamelCase);
String[] split = mapperLocations.split(",");
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource[] resources1 = new Resource[0];
for (int i = 0; i < split.length; i++) {
resources1 = (Resource[]) ArrayUtils.addAll(pathMatchingResourcePatternResolver.getResources(split[i]), resources1);
}
TypeHandler<?>[] typeHandlers = new TypeHandler[1];
typeHandlers[0] = new StringCodeEnumTypeHandler(DataSourceConfig.class);
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
sqlSessionFactoryBean.setMapperLocations(resources1);
sqlSessionFactoryBean.setConfiguration(configuration);
sqlSessionFactoryBean.setTypeHandlers(typeHandlers);
if (interceptors != null) {
sqlSessionFactoryBean.setPlugins(interceptors);
}
return sqlSessionFactoryBean;
}
/**
* 注入 DataSourceTransactionManager 用于事务管理
*/
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dynamicDataSource());
}
}
@Component
public class DataSourceConfigurer extends AbstractBeanFactoryAwareAdvisingPostProcessor implements InitializingBean {
/**
* 切面拦截注入数据源
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
Pointcut pointcut = new AnnotationMatchingPointcut(null, DataSource.class);
this.advisor = new DefaultPointcutAdvisor(pointcut,new DynamicDataSourceInterceptor());
}
}
@Configuration
public class DruidConfiguration {
/**
* 注册一个StatViewServlet
* @return
*/
@Bean
public ServletRegistrationBean DruidStatViewServle2(){
//org.springframework.boot.context.embedded.ServletRegistrationBean提供类的进行注册.
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
//添加初始化参数:initParams
//白名单:
servletRegistrationBean.addInitParameter("allow","");
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
servletRegistrationBean.addInitParameter("deny","192.168.1.73");
//登录查看信息的账号密码.
servletRegistrationBean.addInitParameter("loginUsername","admin");
servletRegistrationBean.addInitParameter("loginPassword","123456");
//是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable","false");
return servletRegistrationBean;
}
/**
* 注册一个:filterRegistrationBean
* @return
*/
@Bean
public FilterRegistrationBean druidStatFilter2(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
//添加过滤规则.
filterRegistrationBean.addUrlPatterns("/*");
//添加不需要忽略的格式信息.
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
//配置数据库的基本连接信息
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource")//在application.properties中读取配置信息注入到DruidDataSource里
public DataSource dataSource(){
DruidDataSource druidDataSource = DataSourceBuilder.create().type(DruidDataSource.class).build();
druidDataSource.setInitialSize(3);//初始化物理连接的数量
try {
druidDataSource.addFilters("stat,wall");//stat是sql监控,wall是防火墙(如果不添加则监控无效),不能添加log4j不然会出错
} catch (SQLException e) {
e.printStackTrace();
}
return druidDataSource;
}
}
public class DynamicDataSource extends AbstractRoutingDataSource {
@Nullable
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDB();
}
}
/**
* 自定义数据源拦截器
*/
public class DynamicDataSourceInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Method method = methodInvocation.getMethod();
String dataSource = DataSourceConstants.DEFAULT_DATA_SOURCE;
try {
if(method.isAnnotationPresent(DataSource.class)){
DataSource annotation = method.getAnnotation(DataSource.class);
dataSource = annotation.value();
}
}catch (Exception e){
e.printStackTrace();
}
//切换数据源
DataSourceContextHolder.setDB(dataSource);
Object preceed = methodInvocation.proceed();
DataSourceContextHolder.clearDB();
return preceed;
}
}
/**
* 常量
*/
public class DataSourceConstants {
public static final String DEFAULT_DATA_SOURCE = "defaultDataSource";
public static final String PRESTO_DATA_SOURCE = "prestoDataSource";
}
public class DataSourceContextHolder {
/**
* 默认数据源
*/
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
// 设置数据源名
public static void setDB(String dbType) {
contextHolder.set(dbType);
}
// 获取数据源名
public static String getDB() {
return (contextHolder.get());
}
// 清除数据源名
public static void clearDB() {
contextHolder.remove();
}
}
@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({ICodeEnum.class})
public class StringCodeEnumTypeHandler<E extends ICodeEnum> extends BaseTypeHandler<E> {
private Class<E> type;
public StringCodeEnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E e, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setString(i, (String) e.getCode());
} else {
ps.setObject(i, e.getCode(), jdbcType.TYPE_CODE);
}
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
String s = rs.getString(columnName);
return s == null ? null : CodeEnumAdapter.toCodeEnum(s, type);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String s = rs.getString(columnIndex);
return s == null ? null : CodeEnumAdapter.toCodeEnum(s, type);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return s == null ? null : CodeEnumAdapter.toCodeEnum(s, type);
}
}
public interface ICodeEnum<T> {
T getCode();
}
public class CodeEnumAdapter {
public static <T> T toCodeEnum(Object code, Class<T> type) {
if (!type.isEnum()) {
throw new IllegalArgumentException(
String.format("type must be Enum,type : %s", type.getName()));
}
if (!ICodeEnum.class.isAssignableFrom(type)) {
throw new IllegalArgumentException(
String.format("type must be sub class by ICodeEnum,type : %s", type.getName()));
}
for (T t : type.getEnumConstants()) {
ICodeEnum codeEnum = (ICodeEnum) t;
if (Objects.equals(codeEnum.getCode(), code)) {
return t;
}
}
throw new IllegalArgumentException(
"Cannot convert " + code + " to " + type.getSimpleName() + " by code.");
}
}
四,mapper配置
在mapper接口的 要使用presto数据源的接口加上自定义注解@DataSource

在xml文件select节点statementType属性必须指定为STATEMENT
所以sql不能进行预编译,即不能使用#{},只能采用${}的方式赋值
