BUG记录

BUG[1]: Tomcat多个SpringBoot项目部署

日期:

2018/7/18

问题描述:

在Tomcat部署第二个项目时,发现无法访问第二个项目,查看Tomcat日志时发现报错:

1
2
3
4
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
18-Jul-2018 14:07:59.394
严重 [main] org.springframework.boot.SpringApplication.reportFailure Application run failed
org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [HikariDataSource (HikariPool-2)] with key 'dataSource'; nested exception is javax.management.InstanceAlreadyExistsException: com.zaxxer.hikari:name=dataSource,type=HikariDataSource

解决过程:

尝试在application.properties中添加spring.jmx.enabled=false

思考原因:

JMX,即Java Management Extensions(JMX)提供了一种监视和管理应用程序的标准机制,默认情况下,Spring Boot将创建一个mBeanServer其Bean Id为“mBeanServer”,并公开任意使用Spring JMX注释(如@ManagedResource,@ ManagedAttribute,@ ManagedOperation)的Bean。

每个JMX Bean都必须具有对象名称,该名称为JMX类的一个实例class?ObjectName,必须符合JMX规范定义的语法,即对象名称必须包含域和键属性列表。

在application.properties中添加spring.jmx.default-domain: test 可以将属性设置为某个值,由于域名是任意的,这可以避免两个应用程序之间的名称冲突。

或者通过spring.jmx.enabled=false直接禁用JMX,或者说忽略注册失败registration failures,而不禁用JMX,在配置类@Configuration中添加

@EnableMBeanExport(registration=RegistrationPolicy.IGNORE_EXISTING)

BUG[2]: Spring轻量Task无法满足需求,改用SqlServer数据库定时任务

日期:

2018/7/23

问题描述:

在设计定时器进行批次结束系列操作时,发现spring自带的轻量级quartz定时任务task不支持年份

解决过程:

首先想到的解决方法:

  1. 使用quartz
  2. 改变思路,不去run一个跨长时间的定时器而是一个每天检查是否批次结束的定时器,那么轻量级的task和数据库定时任务都是可以解决的方案,因为数据库比项目会更稳定运行,所以先考虑数据库定时任务解决方案。

配置定时作业时遇到了些问题:

  • 启动Sql Server代理,服务中打开Sql Server代理MSSQLSERVER
  • 在数据库属性中点选启动代理服务器账号,仍显示已禁用代理XP

执行以下sql语句

1
2
3
4
5
6
7
8
sp_configure 'show advanced options', 1;
GO
RECONFIGURE WITH OVERRIDE; --加上WITH OVERRIDE
GO
sp_configure 'Agent XPs', 1;
GO
RECONFIGURE WITH OVERRIDE --加上WITH OVERRIDE
GO

新建作业

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*存储过程,进行批次结束检查,并执行对应操作*/
CREATE PROCEDURE PR_BatchEndOperas
AS
BEGIN
declare @nowDate varchar(10),@nowTime datetime
--赋值
set @nowDate = CONVERT(varchar(10),GETDATE(),120)
print @nowDate
set @nowTime = CONVERT(datetime,GETDATE(),120)
print @nowTime
--使用select语句赋值
declare @batchId varchar(60)
-- +1表示截至日结束后日执行
select @batchId = BID from QGZX_BATCH where CONVERT(varchar(10),ApplySelectEnd+1,120) = @nowDate
print @batchId
--使用update语句赋值
if(@batchId is not null)
begin
/*批次结束,收尾工作-岗位申请*/
update QGZX_POSITION_APPLY set UnitApplyStatus = '-3',
CenterAuditorID = '0',
CenterAuditorName = '系统自动',
CenterAuditTime = @nowTime,
CenterAuditComment = '批次结束,勤工助学中心未处理,自动拒绝'
where BID = @batchId and UnitApplyStatus = '1'
declare @positionId varchar(60)
--定义一个游标pid
declare position_cur cursor for(select [positionId] = PID from QGZX_POSITION where BID = @batchId)
--打开游标
open position_cur
--读取游标
fetch next from position_cur into @positionId
--返回被fetch语句执行的最后游标的状态
while @@fetch_status=0
begin
--print @positionId
print @positionId
/*批次结束,收尾工作-学生申请*/
update QGZX_STUDENT_APPLY set AuditStatus = '-1',
CollegeReviewerID = '0',
CollegeReviewerName = '系统自动',
CollegeReviewTime = @nowTime,
CollegeReviewerComment = '批次结束,系部未处理,自动拒绝'
where PID = @positionId and AuditStatus = '1'
update QGZX_STUDENT_APPLY set AuditStatus = '-4',
StuWorkReviewerID = '0',
StuWorkReviewerName = '系统自动',
StuWorkReviewTime = @nowTime,
StuWorkReviewerComment = '批次结束,学工处未处理,自动拒绝'
where PID = @positionId and AuditStatus = '2'
update QGZX_STUDENT_APPLY set AuditStatus = '-4',
StuWorkReviewerID = '0',
StuWorkReviewerName = '系统自动',
StuWorkReviewTime = @nowTime,
StuWorkReviewerComment = '批次结束,无部门调剂,自动拒绝'
where PID = @positionId and AuditStatus = '-2'
update QGZX_STUDENT_APPLY set AuditStatus = '-3',
DepReviewerID = '0',
DepReviewerName = '系统自动',
DepReviewerTime = @nowTime,
DepReviewerComment = '批次结束,用人部门未处理,自动拒绝'
where PID = @positionId and AuditStatus = '3'
fetch next from position_cur into @positionId
end
close position_cur
--摧毁游标
deallocate position_cur
end
END
exec PR_BatchEndOperas
/*删除存储过程*/
drop proc PR_BatchEndOperas

BUG[3]: Spring-data-jpa分页BUG

日期:

2018/9/6

问题描述:

Spring-data-jpa处理分页时出现BUG,使用场景:多表关联汇总,原生SQL语句,用接口存储每行的数据,JPA分页每次返回一页数据

CODE(修改后):

Service层

1
2
3
4
5
6
7
8
9
10
public Page<FacilitiesReportSummary> searchFacilitiesReports(int schoolYear, int semester, int page, int limit){
List<Sort.Order> list = new ArrayList<>();
list.add(new Sort.Order(Sort.Direction.ASC,"classId"));
list.add(new Sort.Order(Sort.Direction.ASC,"informorId"));
list.add(new Sort.Order(Sort.Direction.ASC,"weekNum"));
Pageable pageable = PageRequest.of(page-1,limit);
pageable.getSortOr(Sort.by(list));
return facilitiesReportSummaryRepository.findFacilitiesReportSummary(
schoolYear, semester, "001", pageable);
}

Repository层

1
2
3
4
5
6
@Query(nativeQuery = true,value = "select T_PJGL_INSTALLATION_PJ.*,a.isOk from T_PJGL_INSTALLATION_PJ left outer join (select classId,informorId,weekNum,sum(cast(isOk as int)) as isOk from T_PJGL_INSTALLATION_PJ  where schoolYear = :schoolYear and semester = :semester group by classId,informorId,weekNum) a on a.classId = T_PJGL_INSTALLATION_PJ.classId and a.informorId = T_PJGL_INSTALLATION_PJ.informorId and a.weekNum = T_PJGL_INSTALLATION_PJ.weekNum where evaluateItemId = :evaluateItemId"
,countQuery = "select count(*) from T_PJGL_INSTALLATION_PJ inner join (select classId,informorId,weekNum,sum(cast(isOk as int)) as isOk from T_PJGL_INSTALLATION_PJ where schoolYear = :schoolYear and semester = :semester group by classId,informorId,weekNum) a on a.classId = T_PJGL_INSTALLATION_PJ.classId and a.informorId = T_PJGL_INSTALLATION_PJ.informorId and a.weekNum = T_PJGL_INSTALLATION_PJ.weekNum where evaluateItemId = :evaluateItemId ")
Page<FacilitiesReportSummary> findFacilitiesReportSummary(@Param("schoolYear") int schoolYear,
@Param("semester") int semester,
@Param("evaluateItemId") String evaluateItemId,
Pageable pageable);

BUG提示:

SQLServerException: The column name XXX is not valid

解决过程:

尝试了各种方法,翻阅官方文档,stackoverflow等论坛,都没解决问题,但查找的过程中也慢慢的缩小了BUG产生原因范围,大概猜到首先是JPA分页功能自动生成SQL和实体类间不匹配的问题,所以尝试修改返回参数皆为*,之前是实体类的属性,发现问题解决。

BUG[4]: SpringBoot事务不能正常回滚

日期:

2018/9/7

问题描述:

SpringBoot @Transactional 事务中自行抛出异常时不能回滚,已执行的DML操作产生了垃圾数据

产生原因:

上网查找错误原因,首先Spring的事务默认情况下针对Unchecked Exception即运行时异常(之前有总结异常相关知识:Java知识点总结 (一)),针对RuntimeException及其子类进行回滚,而检查式异常,包括try-catch捕获的则不会回滚,除非在catch模块中手动的调用事务回滚。

解决过程:

  1. 可以抛出运行时异常即可解决问题
  2. 可在advice中添加自定义Exception
  3. 可在catch块中手动调用事务回滚

果断用方法一,成功解决BUG