【发布时间】:2021-04-24 22:36:32
【问题描述】:
最近我们遇到了一个问题,即数据库中的记录正在更新,而我们只通过 java api 进行读取操作。下面是我们springboot应用的代码sn-p
public List<ResultDto> getSomethingByColumnA(String arg1, String arg2, String arg3)
return myRepo.findSomethingByColumnA(param1, param2, param3, ResultDto.class)
.stream().map(v -> {
String varErrRec = v.getErrorRecByerl();
varErrRec = (varErrRec == null) ? "" : varErrRec;
String erlTotalRec = v.getTotalRecByerl();
erlTotalRec = (erlTotalRec == null) ? "" : erlTotalRec;
String varErrRecByRule = v.getErrCountByerlRule();
varErrRecByRule = (varErrRecByRule == null) ? "" : varErrRecByRule;
Pattern glPattern = Pattern.compile(glName + ":(.*?),");
Pattern glerlRulePattern = Pattern.compile(glName + "\\|(.*?)\\$");
Matcher erlErrMatcher = glPattern.matcher(varErrRec);
Matcher erlTotalMatcher = glPattern.matcher(erlTotalRec);
Matcher errByRuleMatcher = glerlRulePattern.matcher(varErrRecByRule + "$");
v.setTotalRec(0L);
v.setErrorRec(0L);
v.setErrByRule(null);
while (erlErrMatcher.find()) {
v.setErrorRec(Long.valueOf(erlErrMatcher.group(1)));
break;
}
while (erlTotalMatcher.find()) {
v.setTotalRec(Long.valueOf(erlTotalMatcher.group(1)));
break;
}
while (errByRuleMatcher.find()) {
System.out.println(errByRuleMatcher.group(1));
v.setErrByRule(errByRuleMatcher.group(1));
break;
}
return v;
}).collect(Collectors.toList());
}
findBy 方法的 myRepo 代码 sn-p
@Query("select s from tableA s, tableB t where someCondition order by aColumn ASC")
<T> Collection<T> findSomethingByColumnA(@Param("param1") String param1, @Param("param2")Date param2, @Param("param3")Date param3, Class<T> ctype);
@Projection(name="proj1", types= MyTable.class)
public interface ResultDto{
Long getRunId();
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern ="dd MMM yyyy")
Date getValidateDt();
..some more getters and setters
}
@Entity
@Table(name = "MY_TABLE_NAME")
@Data
public class MyTable implements Serializable {
@Id
@Column(name="ID")
private long id;
.. some more fields
}
我添加了以下属性以启用日志以进行调试
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
在下面记录sn-p:
2021-01-19 10:22:39.455 DEBUG 57901 --- [nio-9000-exec-4] org.hibernate.SQL : select ..query
2021-01-19 10:22:39.455 TRACE 57901 --- [nio-9000-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [CLOB] - [%textA%]
2021-01-19 10:22:39.456 TRACE 57901 --- [nio-9000-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [TIMESTAMP] - [Wed Jan 01 00:00:00 EST 2020]
2021-01-19 10:22:39.457 TRACE 57901 --- [nio-9000-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [TIMESTAMP] - [Tue Jan 19 00:00:00 EST 2021]
2021-01-19 10:22:39.552 DEBUG 57901 --- [nio-9000-exec-4] org.hibernate.SQL : update MY_TABLE_NAME set ...query
2021-01-19 10:22:39.553 TRACE 57901 --- [nio-9000-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [0]
2021-01-19 10:22:39.553 TRACE 57901 --- [nio-9000-exec-4] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [6901]
.
.
binding parameter [16]
如您所见,UPDATE 语句在 SELECT 语句之后立即执行!奇怪的是它发生在服务器上(开发、阶段和产品)。但是,当我在 STS(eclipse)中使用相同的代码将其指向 dev/stage/prod 属性(弹簧配置文件)并在我的系统中进行测试时,这个问题没有发生!什么可能导致执行更新语句?
UPDATE : SELECT statemnt 获取 MY_TABLE_NAME 的 16 列,所有这些列都使用 UPDATE 查询进行更新
UPDATE 查询的执行次数与 SELECT 查询的结果一样多。假设 SELECT 查询返回 10 行,UPDATE 查询将执行 10 次以更新所有这 10 行!
是不是因为 .stream().map(v) 中修改了实体?
v.setTotalRec(Long.valueOf(0));
v.setErrorRec(Long.valueOf(0));
v.setErrByRule(null);
【问题讨论】:
-
用 0 和 6901 更新的那两个字段是什么?
-
@Antoniossss 共有 16 个字段正在更新(包括上面的 0 和 6901)。这些是 SELECT 语句中的 MY_TABLE_NAME 的 16 列
-
您是在类级别添加
@Transactional还是从另一个@Transactional注释方法调用此方法? -
No.. 在类级别不使用@Transactional 并且调用方法/类也不是事务性的
标签: java oracle spring-boot jpa spring-data-jpa