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

Spring Boot关联查询有值但地区字段返回Null问题求助

问题解决:原生SQL查询后Transient字段返回Null的问题

问题原因

你使用原生SQL查询时,JPA仅会自动映射Sellars实体中带有@Column注解的持久化字段(如sellarName、fk_city_id)。而被@Transient标注的country、state、cityName不属于数据库持久化字段,JPA不会自动将查询结果中的对应列值赋值给这些字段,因此返回Null。


解决方案

方案1:使用DTO接收查询结果(推荐)

创建专门的DTO类封装返回数据,避免污染实体类结构:

// 卖家地区信息DTO
public class SellarRegionDTO {
    private Long id;
    private String sellarName;
    private String country;
    private String state;
    private String cityName;

    // 构造函数参数顺序必须与SQL查询列顺序完全一致
    public SellarRegionDTO(Long id, String sellarName, String country, String state, String cityName) {
        this.id = id;
        this.sellarName = sellarName;
        this.country = country;
        this.state = state;
        this.cityName = cityName;
    }

    // 生成getter/setter(可使用Lombok简化)
}

修改Repository查询方法:

@Repository
public interface SellarsRepository extends JpaRepository<Sellars, Long>{
      @Query(value = "SELECT u.id, u.sellarName, c.country, s.state, ci.cityName" +
      " FROM tbl_sellars u" + " JOIN tbl_city ci ON u.fk_city_id = ci.id" +
      " JOIN tbl_state s ON ci.fk_state_id = s.id" +
      " JOIN tbl_country c ON s.fk_country_id = c.id", nativeQuery = true)
      List<SellarRegionDTO> getAllSellarsWithRegion();
}

方案2:用@SqlResultSetMapping映射到实体Transient字段

如果必须使用Sellars实体接收结果,可通过定义结果集映射指定字段对应关系:

  1. 在Sellars实体上添加映射配置:
@Entity(name = "tbl_sellars")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@SqlResultSetMapping(
    name = "SellarsWithRegionMapping",
    entities = @EntityResult(
        entityClass = Sellars.class,
        fields = {
            @FieldResult(name = "id", column = "id"),
            @FieldResult(name = "sellarName", column = "sellarName"),
            @FieldResult(name = "country", column = "country"),
            @FieldResult(name = "state", column = "state"),
            @FieldResult(name = "cityName", column = "cityName")
        }
    )
)
public class Sellars extends CommonEntity {
    // 原有字段保持不变
}
  1. 修改Repository查询方法,指定使用该映射:
@Repository
public interface SellarsRepository extends JpaRepository<Sellars, Long>{
      @Query(value = "SELECT u.id, u.sellarName, c.country, s.state, ci.cityName" +
      " FROM tbl_sellars u" + " JOIN tbl_city ci ON u.fk_city_id = ci.id" +
      " JOIN tbl_state s ON ci.fk_state_id = s.id" +
      " JOIN tbl_country c ON s.fk_country_id = c.id", 
      nativeQuery = true,
      resultSetMapping = "SellarsWithRegionMapping")
      List<Sellars> getAllSellarsWithRegion();
}

方案3:添加@ManyToOne关联(可选)

若允许在Sellars中添加关联注解,可通过关联对象动态获取地区信息:

@Entity(name = "tbl_sellars")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Sellars extends CommonEntity {
    
    @Column(name = "sellarName")
    String sellarName;
    
    @ManyToOne(fetch = FetchType.LAZY) // 懒加载避免性能损耗
    @JoinColumn(name = "fk_city_id", insertable = false, updatable = false)
    private City city;

    // 通过关联对象动态返回地区信息
    @JsonProperty
    public String getCountry() {
        return city != null && city.getState() != null && city.getState().getCountry() != null 
               ? city.getState().getCountry().getCountry() : null;
    }

    @JsonProperty
    public String getState() {
        return city != null && city.getState() != null ? city.getState().getState() : null;
    }

    @JsonProperty
    public String getCityName() {
        return city != null ? city.getCityName() : null;
    }

    // 其他原有字段和方法
}

Repository使用JPQL查询关联数据:

@Repository
public interface SellarsRepository extends JpaRepository<Sellars, Long>{
      @Query("SELECT s FROM tbl_sellars s JOIN FETCH s.city c JOIN FETCH c.state st JOIN FETCH st.country")
      List<Sellars> getAllSellarsWithRegion();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:45:12