application-dev.yml文件内容: spring: datasource: enabled: true url: jdbc:mysql://127.0.0.1:3306/lt-iot?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false username: root password: root # 使用druid数据源 type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver # 初始化大小,最小,最大 initialSize: 1 minIdle: 1 maxActive: 20 # 配置获取连接等待超时的时间 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 validationQuery: select 'x' testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #是否缓存preparedStatement,也就是PSCache 官方建议MySQL下建议关闭 个人建议如果想用SQL防火墙 建议打开 maxPoolPreparedStatementPerConnectionSize: 20 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 filters: stat,wall,log4j # 是否显示输出慢日志 logSlowSql: false # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合并多个DruidDataSource的监控数据 useGlobalDataSourceStat: true db: mybatis: typeAliasesPackage: com.lenovo.esim.cloud.order.*.dao mapperLocations: classpath:mappers/*Mapper.xml configLocation: classpath:mybatis-config.xml
配置相关的实体类
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 设置配置扫描实体类的路径相关的 */ @ConfigurationProperties(prefix = "spring.db.mybatis") @Component @Data public class MybatisConfigurationProperties { public String typeAliasesPackage; public String mapperLocations; public String configLocation; }
配置数据源和事物
import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.fastjson.JSON; import com.lenovo.esim.cloud.database.mybatis.Mapper; import com.lenovo.esim.cloud.database.mybatis.MyMapperScan; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.interceptor.TransactionInterceptor; import javax.sql.DataSource; import java.util.Properties; @Configuration @EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class) @EnableConfigurationProperties(MybatisConfigurationProperties.class) @MyMapperScan(basePackages = "${spring.db.mybatis.typeAliasesPackage}", annotationClass = Mapper.class, sqlSessionFactoryRef = "sqlSessionFactory") public class MybatisDataSourceConfiguration { @Autowired MybatisConfigurationProperties mybatisConfigurationProperties; @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource() { return new DruidDataSource(); } @Bean public DataSourceTransactionManager transactionManager() { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(druidDataSource()); return transactionManager; } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { System.out.println(JSON.toJSON(mybatisConfigurationProperties)); SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(druidDataSource()); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sessionFactory.setConfigLocation(resolver.getResource(mybatisConfigurationProperties.configLocation)); sessionFactory.setMapperLocations(resolver.getResources(mybatisConfigurationProperties.mapperLocations)); SqlSessionFactory resultSessionFactory = sessionFactory.getObject(); return resultSessionFactory; } @Bean(name = "txAdvice") public TransactionInterceptor getAdvisor() throws Exception { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(druidDataSource()); Properties properties = new Properties(); properties.setProperty("get*", "PROPAGATION_REQUIRED,-Exception,readOnly"); properties.setProperty("add*", "PROPAGATION_REQUIRED"); properties.setProperty("save*", "PROPAGATION_REQUIRED"); properties.setProperty("insert*", "PROPAGATION_REQUIRED"); properties.setProperty("update*", "PROPAGATION_REQUIRED"); properties.setProperty("delete*", "PROPAGATION_REQUIRED"); TransactionInterceptor tsi = new TransactionInterceptor(transactionManager,properties); return tsi; } @Bean public BeanNameAutoProxyCreator txProxy() { BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator(); creator.setInterceptorNames("txAdvice"); creator.setBeanNames("*Service", "*ServiceImpl"); creator.setProxyTargetClass(true); return creator; } }
import com.lenovo.esim.cloud.database.mybatis.MyMapperScan; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.mapper.ClassPathMapperScanner; import org.mybatis.spring.mapper.MapperFactoryBean; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; /** * 自定义重新扫描支持${}取值 */ @Slf4j @EnableConfigurationProperties(MybatisConfigurationProperties.class) public class MybatisScannConfig implements ImportBeanDefinitionRegistrar,EnvironmentAware { private Environment env; private ResourceLoader resourceLoader; public MybatisScannConfig(){ } @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MyMapperScan.class.getName())); ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); if(this.resourceLoader != null) { scanner.setResourceLoader(this.resourceLoader); } Class annotationClass = annoAttrs.getClass("annotationClass"); if(!Annotation.class.equals(annotationClass)) { scanner.setAnnotationClass(annotationClass); } Class markerInterface = annoAttrs.getClass("markerInterface"); if(!Class.class.equals(markerInterface)) { scanner.setMarkerInterface(markerInterface); } Class generatorClass = annoAttrs.getClass("nameGenerator"); if(!BeanNameGenerator.class.equals(generatorClass)) { scanner.setBeanNameGenerator((BeanNameGenerator) BeanUtils.instantiateClass(generatorClass)); } Class mapperFactoryBeanClass = annoAttrs.getClass("factoryBean"); if(!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) { scanner.setMapperFactoryBean((MapperFactoryBean)BeanUtils.instantiateClass(mapperFactoryBeanClass)); } scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef")); scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef")); ListbasePackages = new ArrayList (); for (String pkg : annoAttrs.getStringArray("value")) { if (StringUtils.hasText(pkg)) { basePackages.add(parsePlaceHolder(pkg)); } } for (String pkg : annoAttrs.getStringArray("basePackages")) { if (StringUtils.hasText(pkg)) { basePackages.add(parsePlaceHolder(pkg)); } } for (Class> clazz : annoAttrs.getClassArray("basePackageClasses")) { basePackages.add(ClassUtils.getPackageName(clazz)); } scanner.registerFilters(); scanner.doScan(StringUtils.toStringArray(basePackages)); } private String parsePlaceHolder(String pro) { if (pro != null && pro.contains(PropertySourcesPlaceholderConfigurer.DEFAULT_PLACEHOLDER_PREFIX)) { String proGetKeys=pro.substring(2, pro.length() - 1); String value = env.getProperty(proGetKeys); if (log.isDebugEnabled()) { log.debug("find placeholder value " + value + " for key " + pro); } if (null == value) { throw new IllegalArgumentException("property " + pro + " can not find!!!"); } return value; } return pro; } @Override public void setEnvironment(Environment environment) { this.env = environment; } }
/** * 注解开启扫描路径 */ import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.lenovo.esim.cloud.database.config.MybatisScannConfig; import org.mybatis.spring.annotation.MapperScannerRegistrar; import org.mybatis.spring.mapper.MapperFactoryBean; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.Import; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented @Import({MybatisScannConfig.class}) public @interface MyMapperScan { String[] value() default {}; String[] basePackages() default {}; Class>[] basePackageClasses() default {}; Class extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; Class extends Annotation> annotationClass() default Annotation.class; Class> markerInterface() default Class.class; String sqlSessionTemplateRef() default ""; String sqlSessionFactoryRef() default ""; Class extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class; }