如何解决JpaRepository findBy 查询SELECT正在更新数据库中的记录
最近我们遇到了一个问题,即我们只通过 java api 执行读取操作的数据库中的记录正在更新。下面是我们的 springboot 应用程序的代码片段
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());
}
@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
下面的日志片段:
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 属性(spring 配置文件)并在我的系统中进行测试时,这个问题没有发生!什么可能导致执行更新语句?
UPDATE : SELECT 语句获取 MY_TABLE_NAME 的 16 列,并且所有这些列都使用 UPDATE 查询进行更新
UPDATE 查询的执行次数与 SELECT 查询的结果一样多。假设 SELECT 查询返回 10 行,UPDATE Query 将执行 10 次以更新所有这 10 行!
是不是因为实体在 .stream().map(v) 中被修改了?
v.setTotalRec(Long.valueOf(0));
v.setErrorRec(Long.valueOf(0));
v.setErrByRule(null);
解决方法
是不是因为实体在 .stream().map(v)
中被修改了?
是的,这可以说是 JPA 的定义特性:您加载实体,修改它们并在事务结束时(实际上是会话,但大部分相同)JPA 从托管实体收集所有修改并更新它们的状态数据库。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。