【问题标题】:findAllById() returns all equivalent recordsfindAllById() 返回所有等效记录
【发布时间】:2022-01-23 03:31:33
【问题描述】:

我将函数实现为“select * from stat where id = ?”使用 Spring Boot; JPA 方法 findAllById(),但它返回所有等效记录。 请告诉我应该如何修复代码。

create table stat(
    id integer
    , row integer
    , col integer
    , data double precision not null
    , constraint stat_pk1 primary key (id, row, col)
)
otnj=# select * from stat;
id | row | col | data
----+------+-----+----------
1 | 1964 | 1 | 352832
1 | 1965 | 1 | 366649
1 | 1966 | 1 | 432937
...
1 | 2020 | 1 | 4115828
1 | 2021 | 1 | 173263
(58 rows)
package com.sct.entity;

import java.io.Serializable;
import java.util.Objects;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class StatId implements Serializable {

        private static final long serialVersionUID = 1289075301160465252L;

        @Column(name = "id")
        private Integer id;

        public StatId() {
        }

        @Override
        public int hashCode() {
                return Objects.hash(id);
        }

        @Override
        public boolean equals(Object obj) {
                if (this == obj)
                        return true;
                if (obj == null)
                        return false;
                if (getClass() != obj.getClass())
                        return false;
                StatId other = (StatId) obj;
                return Objects.equals(id, other.id);
        }

        public Integer getId() {
                return id;
        }

        public void setId(Integer id) {
                this.id = id;
        }
}
package com.sct.entity;

import java.io.Serializable;
import java.util.Objects;

import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="stat")
public class StatCell implements Serializable {

        private static final long serialVersionUID = 6501935237628672264L;

        @EmbeddedId
        private StatId id;

        @Column(name = "row")
        private Integer row;

        @Column(name = "col")
        private Integer col;

        @Column(name = "data")
        private Double data;

        public StatCell() {
        }

        @Override
        public int hashCode() {
                return Objects.hash(col, data, id, row);
        }

        @Override
        public boolean equals(Object obj) {
                if (this == obj)
                        return true;
                if (obj == null)
                        return false;
                if (getClass() != obj.getClass())
                        return false;
                StatCell other = (StatCell) obj;
                return Objects.equals(col, other.col) && Objects.equals(data, other.data) && Objects.equals(id, other.id)
                                && Objects.equals(row, other.row);
        }
// getters and setters
}
package com.sct.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.sct.entity.StatCell;
import com.sct.entity.StatId;

@Repository
public interface StatCellRepository extends JpaRepository<StatCell, StatId> {
        List<StatCell> findAll();

        @Query(value="SELECT s FROM StatCell s WHERE id = ?1")
        List<StatCell> findAllById(@Param("id") Iterable<StatId> ids);
}
package com.sct.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sct.entity.StatCell;
import com.sct.entity.StatCellId;
import com.sct.entity.StatId;
import com.sct.repository.StatCellRepository;

@Service
public class StatService {
        protected static final Logger log = LoggerFactory.getLogger(StatService.class);

        @Autowired(required=true)
        private StatCellRepository repo;

        public List<StatCell> findAllById(Integer id) {
                StatId statId = new StatId();
                statId.setId(id);
                List<StatId> statIds = new ArrayList<>();
                statIds.add(statId);

                List<StatCell> cells = repo.findAllById(statIds);
                log.info("cells={}", cells.size());

                return cells;
        }

        public Map<StatCellId, Double> findByIdAsMap(Integer id) {
                Map<StatCellId, Double> map = new HashMap<>();

                for (StatCell cell : findAllById(id)) {
                        StatCellId cellId = new StatCellId();
                        cellId.setId(id);
                        cellId.setCol(cell.getCol());
                        cellId.setRow(cell.getRow());

                        Double data = cell.getData();
                        log.info("col={}, row={}, data={}, hashCode={}",
                                        cell.getCol(), cell.getRow(), data, cellId.hashCode());

                        map.put(cellId, data);
                }

                log.info("map.size={}", map.size());
                return map;
        }
}
2021-12-22 02:32:08.663 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.SQL                        : 
    select
        statcell0_.id as id1_0_,
        statcell0_.col as col2_0_,
        statcell0_.data as data3_0_,
        statcell0_.row as row4_0_ 
    from
        stat statcell0_ 
    where
        statcell0_.id=?
Hibernate: 
    select
        statcell0_.id as id1_0_,
        statcell0_.col as col2_0_,
        statcell0_.data as data3_0_,
        statcell0_.row as row4_0_ 
    from
        stat statcell0_ 
    where
        statcell0_.id=?
2021-12-22 02:32:08.663 TRACE 37572 --- [nio-8081-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
2021-12-22 02:32:08.665 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result set row: 0
2021-12-22 02:32:08.666 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result row: EntityKey[com.sct.entity.StatCell#component[id]{id=1}]
2021-12-22 02:32:08.671 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result set row: 1
2021-12-22 02:32:08.671 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result row: EntityKey[com.sct.entity.StatCell#component[id]{id=1}]
...
2021-12-22 02:32:08.675 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result set row: 56
2021-12-22 02:32:08.675 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result row: EntityKey[com.sct.entity.StatCell#component[id]{id=1}]
2021-12-22 02:32:08.675 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result set row: 57
2021-12-22 02:32:08.675 DEBUG 37572 --- [nio-8081-exec-1] org.hibernate.loader.Loader              : Result row: EntityKey[com.sct.entity.StatCell#component[id]{id=1}]
2021-12-22 02:32:08.676 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Resolving attributes for [com.sct.entity.StatCell#component[id]{id=1}]
2021-12-22 02:32:08.676 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Processing attribute `col` : value = 1
2021-12-22 02:32:08.676 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Attribute (`col`)  - enhanced for lazy-loading? - false
2021-12-22 02:32:08.676 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Processing attribute `data` : value = 352832.0
2021-12-22 02:32:08.676 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Attribute (`data`)  - enhanced for lazy-loading? - false
2021-12-22 02:32:08.676 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Processing attribute `row` : value = 1964
2021-12-22 02:32:08.676 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Attribute (`row`)  - enhanced for lazy-loading? - false
2021-12-22 02:32:08.677 DEBUG 37572 --- [nio-8081-exec-1] o.h.engine.internal.TwoPhaseLoad         : Done materializing entity [com.sct.entity.StatCell#component[id]{id=1}]
2021-12-22 02:32:08.677 DEBUG 37572 --- [nio-8081-exec-1] o.h.e.t.internal.TransactionImpl         : committing
2021-12-22 02:32:08.678  INFO 37572 --- [nio-8081-exec-1] com.sct.service.StatService              : cells=58
2021-12-22 02:32:08.679  INFO 37572 --- [nio-8081-exec-1] com.sct.service.StatService              : col=1, row=1964, data=352832.0, hashCode=32747
2021-12-22 02:32:08.679  INFO 37572 --- [nio-8081-exec-1] com.sct.service.StatService              : col=1, row=1964, data=352832.0, hashCode=32747
2021-12-22 02:32:08.679  INFO 37572 --- [nio-8081-exec-1] com.sct.service.StatService              : col=1, row=1964, data=352832.0, hashCode=32747

在接口StatCellRepository中,无论我是否省略@Query,Iterable,结果:每条记录(col,row,data)总是相同的。 地球上会发生什么?

【问题讨论】:

    标签: postgresql hibernate spring-data-jpa


    【解决方案1】:

    如果你想得到不同的值,你需要:

    1. 将属性“row”和“col”从 StatCell 移动到 StatId 并更改这些实体中的 equals 和 hashcode 方法;
    2. 在仓库中使用方法如下:

    List findAllByIdId(Integer id);

    我认为您会得到相同的值,因为实体 StatId 仅包含“id”。这意味着只有一行应该有一个唯一的值“id”。如果您对表使用了约束键(id、row、col),那么您必须使用 EmbaddedId 中的所有键属性。

    【讨论】:

    • 感谢您的回答。我将 row 和 col 从 StatCell 移动到 StatId 并更改了方法。我更改了逻辑以获取一次或零记录并重复调用此方法而不是获取所有记录(id =?)一次来自回购,因为 StatCell 无法确定 uniq 记录。 @Query("SELECT s FROM StatCell s WHERE id=?1.id AND col=?1.col AND row=?1.row") Optional&lt;StatCell&gt; getByIdOrColOrRow(@Param("id") StatId id); 但是STS报错,好像是参数化查询不好。 hql.internal.ast.ErrorTracker unexpected token: 1.antlr.NoViableAltException
    • 在这段代码中,我没有使用@Query注解,只有没有注解的方法。在第一种情况下,您可以通过 Id 获取行,在第二行中通过约束键获取。 List&lt;StatCell&gt; findAllByIdId(Integer id); Optional&lt;StatCell&gt; findByIdIdAndIdRowAndIdCol(Integer id, Integer rowId, Integer colId);
    • 非常感谢您的评论!您的 findByIdIdAndIdRowAndIdCol() 没有 @Query 返回我预期的结果。
    猜你喜欢
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    • 2021-12-04
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多