一,添加依賴
添加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不能進行預編譯,即不能使用#{},只能采用${}的方式賦值
