大道至简,一个注解完成数据库配置

2,469 阅读4分钟

今天来试试使用一个注解完成数据库配置.最终效果:

2.jpg

开始

SpringBoot这个框架还是挺厉害的,也许有些人认为SpringBoot不算一个框架,它只是Spring的增强工具.

当然Spring对于Java而言有着不可动摇的地位.

就像我之前说的:

天不生Spring,Java万古如长夜.

可是SpringBoot的重要性也不能视而不见.

今天就基于SpringBoot来实现使用一个注解来完成数据库配置.

EnableXXX

SpringBoot中,可以自定义这样一个注解@EnableXXX,就是启用某种功能.

@EnableXXX这个注解上使用@Import这个注解,就可以把配置类,或者什么其他需要Spring管理的东西,注入到Spring容器.

就像下面这样,在启动类上使用这个注解, MybatisExtraConfig.class这个类就会注入到Spring容器中.相当于这个类就由Spring帮你管理了,你可以在这个类里使用@Autowired,或者获取容器等,而且MybatisExtraConfig这个类上不需要使用@Component等注解.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MybatisExtraConfig.class)
public @interface EnableMpExtra {
}

其实不使用@EnableXXX也可以.在resources目录下新建一个文件夹META-INF,然后再新建一个文件spring.factories,然后在spring.factories中设置org.springframework.boot.autoconfigure.EnableAutoConfiguration=等于你的配置类.这样不使用注解,在包被引入的时候,就会自动加载配置类.

动态选择数据库 ImportSelector

我们也可以在@EnableXXX注解里加一些值,在启动类上使用的时候,设置这些值,最终我们取到这些值.这些值就是连接数据库的各种参数,

要获取这些值,就少不了ImportSelector.

最后注解是这样的

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DBSelector.class)
public @interface EnableDbStarter {

    DbType type() default DbType.MySQL;

    String url() default "localhost";

    String port() default "3306";

    String dbName();

    String username() default "root";

    String password();

    String basePackage();
}

DBSelector

public class DBSelector implements ImportSelector {

    public static String url;
    public static String port;
    public static String dbName;
    public static String username;
    public static String password;
    public static String basePackage;

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDbStarter.class.getName()));
        DbType type = attributes.getEnum("type");
        url = attributes.getString("url");
        port = attributes.getString("port");
        dbName = attributes.getString("dbName");
        username = attributes.getString("username");
        password = attributes.getString("password");
        basePackage = attributes.getString("basePackage");

        switch (type) {
            case Oracle:
                return new String[]{OracleConfig.class.getName()};
            case MariaDB:
                return new String[]{MariaDBConfig.class.getName()};
            case SqlServer:
                return new String[]{SqlServerConfig.class.getName()};
            case PostgreSQL:
                return new String[]{PostgreSQLConfig.class.getName()};
            case MySQL:
            default:
                return new String[]{MySqlConfig.class.getName()};
        }
    }
}

这个可以根据枚举值,来选择对应的数据库配置.由于其他数据库暂时不需要,就只写了一个MySQL的.

枚举类

public enum DbType {
    MySQL,
    Oracle,
    PostgreSQL,
    SqlServer,
    MariaDB
}

MySql配置类

这个类上面是没有@Configuration这个注解的,可是由于我们在DBSelectorreturn了这个类,所以这个类也可以被Spring管理的.可以看到这个类中使用了@Bean这个注解,是可以正常使用的.

public class MySqlConfig {

    @Bean("dataSource")
    public DataSource dataSource() {
        try {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://" + DBSelector.url + ":" + DBSelector.port + "/" + DBSelector.dbName + "?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai");
            dataSource.setUsername(DBSelector.username);
            dataSource.setPassword(DBSelector.password);

            dataSource.setInitialSize(1);
            dataSource.setMaxActive(20);
            dataSource.setMinIdle(1);
            dataSource.setMaxWait(60_000);
            dataSource.setPoolPreparedStatements(true);
            dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
            dataSource.setTimeBetweenEvictionRunsMillis(60_000);
            dataSource.setMinEvictableIdleTimeMillis(300_000);
            dataSource.setValidationQuery("SELECT 1");
            return dataSource;
        } catch (Throwable throwable) {
            throw new RuntimeException();
        }
    }

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setVfs(SpringBootVFS.class);
        factoryBean.setTypeAliasesPackage(DBSelector.basePackage);

        Resource[] mapperResources = new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml");
        factoryBean.setMapperLocations(mapperResources);
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.addInterceptor(new SqlExplainInterceptor());
        //分页
        configuration.addInterceptor(new PaginationInterceptor());
        configuration.setUseGeneratedKeys(true);
        factoryBean.setConfiguration(configuration);
        return factoryBean.getObject();
    }

    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "transactionManager")
    public PlatformTransactionManager platformTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "transactionTemplate")
    public TransactionTemplate transactionTemplate(@Qualifier("transactionManager") PlatformTransactionManager transactionManager) {
        return new TransactionTemplate(transactionManager);
    }

}

其他数据库的配置类就是一个空类.就像下面这样,不细说了.

public class OracleConfig {
}

使用方法

第一种

简单点就是,还是在这个项目下,创建Controller,Service,Mapper,Domain,然后新建启动类,然后在启动类上使用@EnableDbStarter这个注解.就是在当前项目中测试.不推荐这种方法,因为看不出来效果.

第二种

可以把这个项目打成Jar包,在其他项目引入.效果比较直观一点,当然如果有maven私服,可以把这个项目发到私服,然后再其他项目使用.

我就是发到了私服,然后在其他项目中引用.

引入依赖,可以看到依赖也少了很多,不用再引入mysql-connectordruid的.

1.jpg 在启动类上使用,在注解上设置数据库相关的信息,因为注解有些值有默认值,就可以少写一点啦.

basePackage是给Mybatis用来扫描别名的.

2.jpg

整个项目结构如下,没有其他配置.

3.jpg

启动看一下

4.jpg

启动成功.

请求一下

5.jpg 数据库

6.jpg

到这里,使用一个注解就完成了数据库的配置.

感兴趣的小伙伴可以试试其他的,比如Swagger配置,Redis配置,Dubbo配置等等,最终简化为一个注解就可以完成,最后肯定很有成就感.

7.gif

最后欢迎大家关注我的公众号 南诏Blog ,共同学习,一起进步。加油🤣

原创不易,转载请标明出处 !!!