findAllById() returns 所有等效记录

findAllById() returns all equivalent records

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

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<>,结果:每条记录(列、行、数据)始终相同。 到底发生了什么?

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

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

List findAllByIdId(Integer id);

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