You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+SQLite多对多关联查询无数据问题排查

问题描述

我正在开发基于Spring Boot和SQLite数据库的项目,其中User与StudyType实体通过jakarta.persistence注解配置多对多关联。

User实体代码:

@Table(name = "users")
@Entity
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // 数据库表主键

    private String userId; // 与主键不同
    
    private String username;
    
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_study_types",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "study_type_id")
    )
    private Set<StudyType> studyTypes;
}

StudyType实体代码:

@Table(name = "study_types")
@Entity
@Data
public class StudyType {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @ManyToMany(mappedBy = "studyTypes")
    private Set<User> users;
}

项目运行后生成users、study_types和user_study_types三张表,我手动插入数据:

INSERT INTO users (user_id, username) VALUES('user01', 'username01');
INSERT INTO study_types (name) VALUES ('intermediate'), ('advanced');
INSERT INTO user_study_types (user_id, study_type_id) VALUES (1, 1), (1, 2);

按预期userId为user01的用户应关联2个StudyType,但通过userRepository.findByUserId('user01')查询到的user实例中studyTypes数量为0,请问原因是什么?

原因分析及解决办法

出现该问题的常见原因及对应解决方式如下:

  • 派生查询未触发关联加载:虽然User实体标注了FetchType.EAGER,但Spring Data JPA的派生查询(如findByUserId)有时不会自动执行关联表的JOIN查询,导致studyTypes集合未被初始化。
    解决:在Repository方法上显式编写JPQL查询,强制加载关联数据:

    @Query("SELECT u FROM User u JOIN FETCH u.studyTypes WHERE u.userId = :userId")
    User findByUserId(@Param("userId") String userId);
    
  • Hibernate一级缓存干扰:如果之前已查询过该用户实例,缓存中的对象未包含关联数据,后续查询会直接复用缓存内容,导致看不到关联的StudyType。
    解决:调用entityManager.refresh(user)刷新实例,或重启应用后重新查询。

  • 关联数据不匹配:手动插入的user_study_types表中user_id值可能与users表的主键id不匹配(比如users表插入后主键id不是1)。
    解决:执行SELECT * FROM users;确认用户的主键id值,再检查user_study_types表中的user_id是否与之对应,修正插入数据。

  • equals/hashCode方法异常:@Data注解生成的equals/hashCode会包含studyTypes集合,当集合未初始化时,可能导致集合被误判为空。
    解决:手动重写User和StudyType的equals/hashCode方法,仅基于主键字段:

    // User类重写示例
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
    

    StudyType类做同样修改即可。

内容的提问来源于stack exchange,提问作者user842225

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:51:19