Springboot配置问题汇总

1、Springboot多数据源配置后导致的打印日志问题
(1)描述:springboot整合多数据源后无法打印控制台没打印sql
(2)原因:因为(mybatis.configuration.log-impl)tk.mybatis 当SqlSessionFactory不存在定义的时候定义SqlSessionFactory;而我们配置多数据源时,重新定义了SqlSessionFactory;因此,如果要打印sql 语句的话,需在我们配置多数据源的SqlSessionFactory时添加。
具体解决方案:
(1)确认application配置

mybatis.configuration.jdbc-type-for-null=NULL
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.type-aliases-package=com.**.entity
mybatis.mapper-locations=classpath*:mapper/**/*Mapper.xml

#### print sql
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

(2)在数据源配置目录下加入MybatisProperties即可

    @Primary
    @Bean(name="damsqlSessionFac")
    public SqlSessionFactory damsqlSessionFactory(@Qualifier("damData") DataSource ds
            , MybatisProperties mybatisConfigLog) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();

        DataSource damDatasource=ds;
        bean.setDataSource(damDatasource);
        //此处设置打印日志问题
        bean.setConfiguration(mybatisConfigLog.getConfiguration());
        return bean.getObject();
    }

2、解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题,一般考虑的问题是mapper的xml对应问题,可考虑如下方向:
(1)是否mapper.java文件上使用了注解@Mapper 或者 在启动类上扫描了Mapper类 @MapperScan(“com.heima.model.mappers”) 【注意扫描的包名是否正确】
(2)注意mapper.xml文件中的namespace是否正确指向到Mapper.java类的位置 【】
(3)注意被调用的方法名在mapper.java中和mapper.xml中的id保持一致性
(4)注意mapper.xml方法的parameterType尽量指定全路径的domain
(5)注意Mapper.java在被调用的地方需要注入@Autowired
(6)最终,一定一定要注意你建立的mapper.xml是xml文件,因为你创建的file在idea上默认会被识别为xml。
如果上述几项未解决问题,可考虑下方
该问题存在的地方为服务启动后的报错,说明在初始化过程中mapper对应的xml已经映射完成,在调用对应的功能是,mybatis找不到对应的typeAliasesPackage,故,可以在sqlsessionfactory中把所有的typeAliasesPackage设置在内,具体的解决方案如下:

    public static String setTypeAliasesPackage(String typeAliasesPackage) {
        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
        List<String> allResult = new ArrayList<String>();
        try {
            for (String aliasesPackage : typeAliasesPackage.split(",")) {
                List<String> result = new ArrayList<String>();
                aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                        + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
                Resource[] resources = resolver.getResources(aliasesPackage);
                if (resources != null && resources.length > 0) {
                    MetadataReader metadataReader = null;
                    for (Resource resource : resources) {
                        if (resource.isReadable()) {
                            metadataReader = metadataReaderFactory.getMetadataReader(resource);
                            try {
                                result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
                            } catch (ClassNotFoundException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                if (result.size() > 0) {
                    HashSet<String> hashResult = new HashSet<String>(result);
                    allResult.addAll(hashResult);
                }
            }
            if (allResult.size() > 0) {
                typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
            } else {
                throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return typeAliasesPackage;
    }
    public Resource[] resolveMapperLocations(String[] mapperLocations) {
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        List<Resource> resources = new ArrayList<Resource>();
        if (mapperLocations != null) {
            for (String mapperLocation : mapperLocations) {
                try {
                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
                    resources.addAll(Arrays.asList(mappers));
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return resources.toArray(new Resource[resources.size()]);
    }

    @Bean(name="creditsqlSessionFac")
    public SqlSessionFactory sqlSessionFactorySecondary(@Qualifier("creditData") DataSource ds) throws Exception {
        String typeAliasesPackage = env.getProperty("mybatis.type-aliases-package");
        String mapperLocations = env.getProperty("mybatis.mapper-locations");
        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
        VFS.addImplClass(SpringBootVFS.class);
        
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(ds);
        bean.setTypeAliasesPackage(typeAliasesPackage);
        bean.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
        return bean.getObject();
    }

3、1 字节的 UTF-8 序列的字节 1 无效
该问题一般解决思路为找到报错位置,将格式强制转换为utf8即可(也可能出现xml文件中utf8设置有误的问题,可作为排查项)
4、解决mybatis resultMap根据type找不到对应的包问题
该问题主要是在mapper.xml中resultmap中type和sql语句中parameterType设置对应的entity无法找到的问题,
具体如下

 <resultMap type="CreditAccessMaster" id="CreditAccessMasterResult">
 <select id="selectCreditAccessMasterList" parameterType="CreditAccessMaster" resultMap="CreditAccessMasterResult">

(1)首先需要查看type和parameterType的名称与mapper的java文件的的命名是否一致。
(2)注意mapper.xml文件中的namespace是否正确指向到Mapper.java类的位置。
(3)注意被调用的方法名在mapper.java中和mapper.xml中的id保持一致性。
(4)名称无误的话则需要在application.properties中配置mybatis的type-aliases-package以及mapper-locations,具体如下所示

mybatis.type-aliases-package=com.**.entity
mybatis.mapper-locations=classpath*:mapper/**/*Mapper.xml

5 springboot数据连接池配置问题
在谈论该问题之前首先需要了解数据访问基本概念:
(1)JDBC
Java数据库连接(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。
JDBC的API主要有:

  • DriverManager:负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接(Connection)。
  • Driver:驱动程序,会将自身加载到DriverManager中去,并处理相应的请求并返回相应的数据库连接(Connection)。
  • Connection:数据库连接,负责与进行数据库间通讯,SQL执行以及事务处理都是在某个特定Connection环境中进行的。可以产生用以执行SQL的Statement
  • Statement:用以执行SQL查询和更新(针对静态SQL语句和单次执行)。
  • PreparedStatement:用以执行包含动态参数的SQL查询和更新(在服务器端编译,允许重复执行以提高效率)。
  • CallableStatement:用以调用数据库中的存储过程。
  • SQLException:代表在数据库连接的建立和关闭和SQL语句的执行过程中发生了例外情况(即错误)。

(2)数据源

可以看到,在 java.sql 中并没有数据源(Data Source)的概念。这是由于在java.sql中包含的是JDBC内核API,另外还有个javax.sql包,其中包含了JDBC标准的扩展API。而关于数据源(Data Source)的定义,就在javax.sql这个扩展包中。

实际上,在JDBC内核API的实现下,就已经可以实现对数据库的访问了,那么我们为什么还需要数据源呢?主要出于以下几个目的:
封装关于数据库访问的各种参数,实现统一管理
通过对数据库的连接池管理,节省开销并提高效率
在Java这个自由开放的生态中,已经有非常多优秀的开源数据源可以供大家选择,比如:DBCP、C3P0、Druid、HikariCP等。

而在Spring Boot 2.x中,对数据源的选择也紧跟潮流,采用了目前性能最佳的HikariCP。
接下来,我们就来具体说说,这个Spring Boot中的默认数据源配置
默认数据源HikariCP
由于Spring Boot的自动化配置机制,大部分对于数据源的配置都可以通过配置参数的方式去改变。

只有一些特殊情况,比如:更换默认数据源,多数据源共存等情况才需要去修改覆盖初始化的Bean内容。本节我们主要讲Hikari的配置。

在Spring Boot自动化配置中,对于数据源的配置可以分为两类:

1、通用配置:以 spring.datasource.* 的形式存在,主要是对一些即使使用不同数据源也都需要配置的一些常规内容。

比如:数据库链接地址、用户名、密码等。通常就这些配置:

spring.datasource.url=jdbc:mysql://**/app
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
2、数据源连接池配置:以 spring.datasource.<数据源名称>.
的形式存在。

比如:Hikari的配置参数就是 spring.datasource.hikari.* 形式。下面这个是我们最常用的几个配置项及对应说明:

spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.idle-timeout=500000
spring.datasource.hikari.max-lifetime=540000
spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.connection-test-query=SELECT 1
这些配置的含义:

spring.datasource.hikari.minimum-idle: 最小空闲连接,默认值10,小于0或大于maximum-pool-size,都会重置为maximum-pool-size

spring.datasource.hikari.maximum-pool-size: 最大连接数,小于等于0会被重置为默认值10;大于零小于1会被重置为minimum-idle的值

spring.datasource.hikari.idle-timeout: 空闲连接超时时间,默认值600000(10分钟),大于等于max-lifetime且max-lifetime>0,会被重置为0;不等于0且小于10秒,会被重置为10秒。

spring.datasource.hikari.max-lifetime: 连接最大存活时间,不等于0且小于30秒,会被重置为默认值30分钟.设置应该比mysql设置的超时时间短

spring.datasource.hikari.connection-timeout: 连接超时时间:毫秒,小于250毫秒,否则被重置为默认值30秒

spring.datasource.hikari.connection-test-query: 用于测试连接是否可用的查询语句。

Druid
Druid是数据库连接池,它能够提供强大的监控和扩展功能。
整合方式:
导入Druid依赖,pom.xml

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.17</version>
    </dependency>

配置application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/xiaomissm
    username: root
    password: 123
    driver-class-name: com.mysql.cj.jdbc.Driver

编写配置类,设置数据源为Druid

@Configuration
public class mydatasourceConfig {


    /**
     *     如果没有配置数据源,也就是数据连接池,会有默认的自动配置的数据源
     *     默认的自动配置是判断容器中没有 DataSource类型的组件才会配,用@ConditionalOnMissingBean({DataSource.class})判断
     *     现在定义为Druid数据源,默认的则不生效
     * @return
     */
    @ConfigurationProperties("spring.datasource") //复用配置文件的数据源配置
    @Bean
    public DataSource dataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
//        druidDataSource.setUrl();
//        druidDataSource.setUsername();
//        druidDataSource.setPassword();
        return druidDataSource;
    }
}

其它配置:配置监控页面、防火墙、web应用等

@Configuration
public class mydatasourceConfig {


    /**
     *     如果没有配置数据源,也就是数据连接池,会有默认的自动配置的数据源
     *     默认的自动配置是判断容器中没有 DataSource类型的组件才会配,用@ConditionalOnMissingBean({DataSource.class})判断
     *     现在定义为Druid数据源,默认的则不生效
     * @return
     */
    @ConfigurationProperties("spring.datasource") //复用配置文件的数据源配置
    @Bean
    public DataSource dataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
//        "stat"打开Druid的监控统计功能,"stat,wall"加入监控和防火墙功能功能
        druidDataSource.setFilters("stat,wall");

        return druidDataSource;
    }

//    配置druid的监控页功能
    @Bean
    public ServletRegistrationBean statViewServlet(){
        StatViewServlet statViewServlet = new StatViewServlet();
        ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*");
        //监控页账号密码:
        registrationBean.addInitParameter("loginUsername","admin");
        registrationBean.addInitParameter("loginPassword","123456");

        return registrationBean;
    }



    /**
     * WebStatFilter 用于采集web-jdbc关联监控的数据。
     */
    @Bean
    public FilterRegistrationBean webStatFilter(){
        WebStatFilter webStatFilter = new WebStatFilter();

        FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(webStatFilter);
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");

        return filterRegistrationBean;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值