微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JpaRepository findBy 查询SELECT正在更新数据库中的记录

如何解决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());
}

findBy 方法的 myRepo 代码片段

@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 举报,一经查实,本站将立刻删除。