【问题标题】:JPQL only returning the first recordJPQL 只返回第一条记录
【发布时间】:2018-09-13 12:11:49
【问题描述】:

这里是 Spring Boot/JPA/Hibernate/MySQL。我有以下表格:

describe states;
+------------+---------------------+------+-----+---------+----------------+
| Field      | Type                | Null | Key | Default | Extra          |
+------------+---------------------+------+-----+---------+----------------+
| state_id   | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| country_id | bigint(20) unsigned | NO   | MUL | NULL    |                |
| state_name | varchar(250)        | NO   |     | NULL    |                |
| state_code | varchar(3)          | YES  | MUL | NULL    |                |
+------------+---------------------+------+-----+---------+----------------+

describe countries;
+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| country_id   | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| country_name | varchar(250)        | NO   | UNI | NULL    |                |
| country_code | varchar(3)          | NO   | UNI | NULL    |                |
+--------------+---------------------+------+-----+---------+----------------+

当我运行SELECT * FROM states WHERE country_id = 1; 时,我得到:

+----------+------------+----------------------+------------+
| state_id | country_id | state_name           | state_code |
+----------+------------+----------------------+------------+
|     3805 |          1 | Alabama              | NULL       |
|     3806 |          1 | Alaska               | NULL       |
|     3807 |          1 | Arizona              | NULL       |
|     3808 |          1 | Arkansas             | NULL       |
|     3810 |          1 | California           | NULL       |
...
|     3860 |          1 | Virginia             | NULL       |
|     3861 |          1 | Washington           | NULL       |
|     3862 |          1 | West Virginia        | NULL       |
|     3863 |          1 | Wisconsin            | NULL       |
|     3864 |          1 | Wyoming              | NULL       |
+----------+------------+----------------------+------------+

(All 50 states)

具有相应 JPA 实体的:

@Entity
@Table(name = "states")
public class State {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @JsonIgnore
    @NotNull
    private String name;

    @Column(name = "state_code")
    @NotEmpty
    private String code;

    @ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.PERSIST, CascadeType.MERGE])
    @JoinColumn(name = "country_id", referencedColumnName = "country_id")
    @NotNull
    @Valid
    private Country country;

    // Getters, setters & constructors
}

@Entity
@Table(name = "countries")
public class Country {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @JsonIgnore
    @NotNull
    private String name;

    @Column(name = "state_code")
    @NotEmpty
    private String code;

    // Getters, setters & constructors
}

我还有以下CrudRepository

public interface StateRepository extends CrudRepository<State, Long> {
    @Query("FROM Province WHERE country = :country")
    public Set<Province> findAllByCountry(@Param("country") Country country);
}

最后我有一个服务方法,它接受 Country 并返回与之关联的所有 States

public Set<Province> getProvincesByCountryCode(Country country) {
    log.info("Country id is " + country.getId());
    Set<Province> provinces = stateRepository.findAllByCountry(country);
    log.info("Found " + provinces.size() + " states associated with this country (" + country.getCode() + ")");

    // TODO: Return 'provinces' once I get this fixed...
    return null;
}

当这个服务方法执行时,它只返回一个List&lt;State&gt;,里面有一个State(所以大小为1),日志输出为:

Country id is 1
Found 1 states associated with this country (US)

所以 MySQL 数据库知道所有 50 个状态,但 StateRepository 只返回 1 个。特别是它返回第一个状态记录(阿拉巴马州),我觉得这很有趣...

很明显,我在CrudRepository 中的 JPQL 有问题,有人能发现缺少什么吗?

【问题讨论】:

  • 您返回的是Set,这意味着您必须正确实现equalshashCode 方法。如果这些没有正确实施,您将丢失Set 中的数据。而是尝试返回ListIterable。您也不需要 @Query,因为 Spring Data JPA 会为您生成它。
  • 感谢您的建议,但这不起作用。
  • 什么不起作用?里面有很多建议。
  • 我将方法改为返回List,但它仍然只返回states表中的第一条记录。
  • 同时删除@Query并将方法更改为findByCountry Spring数据将完成剩下的工作。不需要@JoinColumn。尽管如此,您仍然应该为 JPA (Hibernate) 实现正确的 equalshashCode 以正确解决问题,尤其是在集合和缓存方面。

标签: mysql hibernate spring-boot jpa jpql


【解决方案1】:

使用以下代码:

public interface StateRepository extends JpaRepository<Province, Long> {
    public Set<Province> findAllByCountry(Country country);
}

此外,调试这类东西的最佳方法是在您的应用中启用 sql 日志,查看 sql 生成的日志,您可以轻松找出所见背后发生了什么

【讨论】:

  • 谢谢,我在这里尝试了您的解决方案,但它不起作用(完全相同的结果)。
  • 你在你的app中看到sql查询日志了吗?
【解决方案2】:

最后我只是使用了一个原生查询:

String query = "SELECT * FROM states where country_id = " + countryId;
entityManager.createNativeQuery(query, State.class).getResultList();

像魅力一样工作!

【讨论】:

  • 永远不要连接来构建 SQL 查询!这也不是一个解决方案,而是一个 hack/workaround。
  • 并非没有全貌。您使用部分代码提出问题,并希望我们能神奇地解决您的问题。这显然不会发生。有多种建议,您尝试了一个并停了下来。你没有解释你尝试了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2016-05-22
  • 1970-01-01
相关资源
最近更新 更多