SpringBoot踩坑记

启动

  • WARNING : Your ApplicationContext is unlikely to start due to a @ComponentScan of the default package.
    解决:根据提示,SpringBoot启动类放置目录不正确,报该错时,我的启动类是直接放在java路径下,没有放在程序根包下。
    错误示例:
    在这里插入图片描述
    正确示例
    在这里插入图片描述
  • 应用打包成war包,部署到tomcat中,发现应用没用启动
    解决:启动类继承SpringBootServletInitializer
    public class XxxApplication  extends SpringBootServletInitializer {
       public static void main(String[] args) {
           SpringApplication.run(XxxApplication.class,args);
       }
    
       @Override
       protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
           return builder.sources(XxxApplication.class);
       }
    }
    

动态数据源

  • 错误描述:

The dependencies of some of the beans in the application context form a cycle:
scheduleJobLogService (field protected com.baomidou.mybatisplus.mapper.BaseMapper com.baomidou.mybatisplus.service.impl.ServiceImpl.baseMapper)

scheduleJobLogDao defined in file [E:\xxxx\modules\job\dao\ScheduleJobLogDao.class]

sqlSessionFactory defined in class path resource [com/baomidou/mybatisplus/spring/boot/starter/MybatisPlusAutoConfiguration.class]
┌─────┐
| dataSource defined in class path resource [io/xxx/datasources/DynamicDataSourceConfig.class]
↑ ↓
| firstDataSource defined in class path resource [io/xxx/datasources/DynamicDataSourceConfig.class]
↑ ↓
| org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker
└─────┘

  • 解决:
    项目中配置了动态数据源,但在启动时报了以上错误,根据提示可知,dataSource注入时出现了死循环,一开始是自定义的dataSource(DynamicDataSource),后续又变成了默认的dataSource(org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker),系统存在两个dataSource。所以我们需要去掉默认的DataSource,改为自定义DataSource,以下是具体代码:
    package io.xxx;
    
    import io.xxx.datasources.DynamicDataSourceConfig;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.context.annotation.Import;
    
    @SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
    @Import({DynamicDataSourceConfig.class})
    public class XxxApplication {
        public static void main(String args[]) {
            SpringApplication.run(XxxApplication.class,args);
        }
    }
    

事务回滚

当程序出现异常时,为了避免数据的不一致性,我们需要进行事务的回滚。所以在讲事务回滚之前我们先来看下Java的异常体系。

在这里插入图片描述
图片转载自关于异常体系的解释,读者可点击该链接阅读。

Error是我们无法通过修改程序来解决的异常,比如OutOfMemoryError、ThreadDeath,当这种异常发生时,线程会直接终止;Exception是我们程序编写不当导致的异常,比如空指针,出现该异常时,程序不会终止,而是继续运行下去。

异常分类:
我们可以将异常分为运行时异常(RuntimeException)和非运行时异常(Exception中除了RuntimeException及其子类以外的)。另一方面,我们可以将异常分为受控异常(checked exceptions)和不受控异常(unchecked exceptions)。
1、受控异常(checked exceptions):就是非运行时异常,即Exception中除了RuntimeException及其子类以外的。
2、不受控异常(unchecked exceptions):RuntimeException和Error。

@Transaction实战遇到的问题

我在将该注解添加Service中的一个方法时,发现程序即使出现异常也没有回滚,后来查了几篇文章,讲到Spring默认的事务异常处理机制是:
Spring框架的事务管理默认地只在发生不受控异常时才进行事务回滚。
若程序Catch住了异常,并且没有往外抛,那么该事务不会进行回滚
遇到这种情况,我们可以通过以下两种方式解决:
1、在类或方法前注解配置@Transactional(rollbackFor=Exception.class)
2、在catch中手动进行回滚,添加如下代码:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

笔者在使用第2种方法时,程序报了以下错误

org.springframework.transaction.NoTransactionException: No transaction aspect-managed TransactionStatus in scope异常处理

根据提示,说当前方法没有开启事务,很奇怪,方法上明明加了@Transaction注解,为啥还提示没有加。仔细看了下代码,发现我的这个方法不是直接被外层调用的,外层是先调用了该方法所在类的A方法,然后A方法调用的它,而A方法并没有开启事务。 将A方法添加@Transaction之后,程序可以正常运行了,事务也可以正常回滚。

第三方集成

Mybatis

  • 错误描述:

     Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): io.xxx.modules.xxx.dao.XxxDao.queryList
    	at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:227) ~[mybatis-3.4.6.jar:3.4.6]
    	at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:49) ~[mybatis-3.4.6.jar:3.4.6]
    	at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:65) ~[mybatis-3.4.6.jar:3.4.6]
    	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58) ~[mybatis-3.4.6.jar:3.4.6]
    	at com.sun.proxy.$Proxy83.queryItfAdvancePaymentList(Unknown Source) ~[na:na]
    
  • 解决:
    提示xml文件中没有queryList这个sql,但文件实际是有的,为何找不到呢?网上提供了几种排查方法,我现在简单罗列一下:

    1. xml文件中的 namespace=“xxx.xxx.xxx.Dao” 中的路径是否与接口文件路径一致。
    2. parameterType类型 与 resultType类型是否与接口文件中定义的类型一致。
    3. xml文件扫描路径是否配置正确,否则xml文件无法被扫描到。

    经过上面的排查,我这边问题依旧存在,但上面的排查给了我大体思路:首先,保证自己的xml文件放置的路径正确;其次,保证xml文件和接口文件中的方法名、参数及返回类型匹配。然后按照这两步骤,发现自己的xml文件放置的文件夹在编译之后没有在扫描路径下,如图:
    在这里插入图片描述
    造成上述现象是由于Intellj Idea的显示模式设置造成的,如图
    在这里插入图片描述
    如果一个文件夹下面只有一个文件的话,子文件夹会和父文件夹连接显示,比如mapper.job,如果要建job的同级目录的话只能选中mapper的父文件夹resources,然后新建mapper.realTime文件夹,但这样子建出来的realTime文件夹其实不在mapper下面,因为它实际的名字叫mapper.realTime文件夹。为了避免此显现,建议将‘Compact Middle Packages’选项取消勾选,这样子目录层级分明,不会出错。下图是取消勾选的效果
    在这里插入图片描述

  • 错误描述:
    org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'names' not found. Available parameters are [collection, list]

  • 解决:
    因为Mybatis里面用了foreach标签,需要传递一个list进行遍历,如果在dao层方法直接传递list的话就会报该错误,可以在参数名称前加一个注解解决,代码如下:

    public List<Object> getSomethings(@Param("names")List names)
    

    当然也可以将List参数封装到Map里面,需要注意的是key一定要与dao文件里面遍历的key一致。

  • 错误描述:
    mybatis中查询oracle数据库date类型的时间没有时分秒

  • 解决措施:
    原因出在mybatis中的mapper.xml中对象的属性对应的jdbcType=date。jdbcType=date对应的Java类型是java.sql.date,所以没有时分秒。如果想显示时分秒,对象的属性对应的jdbcType应该设置成TIMESTAMP。

     <result column="CREATE_TIME"  property="createTime" jdbcType="TIMESTAMP"/>
    

Quartz

  • 错误描述:
    Caused by: org.quartz.SchedulerException: ThreadPool class 'org.quartz.simple.SimpleThreadPool' could not be instantiated.
    	at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:841) ~[quartz-2.3.0.jar:na]
    	at org.quartz.impl.StdSchedulerFactory.getScheduler(StdSchedulerFactory.java:1559) ~[quartz-2.3.0.jar:na]
    	at org.springframework.scheduling.quartz.SchedulerFactoryBean.createScheduler(SchedulerFactoryBean.java:650) ~[spring-context-support-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    	at org.springframework.scheduling.quartz.SchedulerFactoryBean.prepareScheduler(SchedulerFactoryBean.java:590) ~[spring-context-support-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    	at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:490) ~[spring-context-support-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1767) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1704) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
    
  • 解决:
    使用Intellij Idea全局搜索SimpleThreadPool这个类,发现其路径为org.quartz.simpl,也就是说simpl后面没有e,好坑的单词。。。

打包

jar包

springboot使用的是maven,通过mvn install指令执行完毕之后,然后java -jar XXX.jar时,提示没有主清单属性
解决:pom文件需要添加一个插件,如下:


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>

重新执行mvn install之后,运行jar包,问题解决。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值