JPA 在应该为空时返回空集 Optional<>

JPA Returning Empty Set When Should Be Empty Optional<>

我有以下两个实体:

@Entity
@Table(name = "organization")
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Organization {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    Long id;

    @Column(name = "name")
    String name;

    @OneToMany(mappedBy = "organization")
    Set<Team> teams;
    
}
@Entity
@Table(name = "team")
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    Long id;

    @Column(name = "name")
    String name;

    @Column(name = "description")
    String description;

    @ManyToOne
    @JoinColumn(name="organization_id", nullable=false)
    Organization organization;
    
}

以及这些实体的以下两个存储库

@Repository
public interface OrganizationRepo extends CrudRepository<Organization, Long> {
    
}
@Repository
public interface TeamRepo extends CrudRepository<Team, Long> {

    Optional<Set<Team>> findByOrganizationId(Long organizationId);

    Optional<Team> findByOrganizationIdAndTeamId(Long organizationId, Long teamId);
    
}

然后我尝试将 findByOrganizationId(..) 方法与一个不存在的 organizationId 一起使用,并希望它 return 一个空的可选值,但我得到的是一个包含 0 个项目的 HashSet<>?有没有一种方法可以使用 JPA 方法实现此功能?

    @Autowired
    TeamRepo repository;

    @ResponseBody
    @GetMapping(value = "/api/v1/organization/{organizationId}/team")
    ResponseEntity<Iterable<Team>> index(@PathVariable Long organizationId) {

        Optional<Set<Team>> result = repository.findByOrganizationId(organizationId);

        if(result.isPresent()) {

            return new ResponseEntity<>(result.get(), HttpStatus.OK);

        } else {

            return new ResponseEntity<>(HttpStatus.NOT_FOUND);

        }

    }

编辑: 由于OrganizationTeams是一对多关系,按理说如果没有Organization,应该return空Optional<>,但如果有一个 Organization 有 0 个或多个团队,它应该 return 一个 Optional<> 有一个 Set<> 零个或多个团队。

当你使用集合作为结果时,你不需要将它包装在 Optional 中,你可以直接使用 isEmpty() 方法检查集合:

@Repository
public interface TeamRepo extends CrudRepository<Team, Long> {

    Set<Team> findByOrganizationId(Long organizationId);

    Optional<Team> findByOrganizationIdAndTeamId(Long organizationId, Long teamId);
    
}




@Autowired
TeamRepo repository;

@ResponseBody
@GetMapping(value = "/api/v1/organization/{organizationId}/team")
ResponseEntity<Iterable<Team>> index(@PathVariable Long organizationId) {

    Set<Team> result = repository.findByOrganizationId(organizationId);

    if(!result.isEmpty()) {

        return new ResponseEntity<>(result, HttpStatus.OK);

    } else {

        return new ResponseEntity<>(HttpStatus.NOT_FOUND);

    }

}

Effective Java 书中指出:容器类型,包括集合、映射、流、数组和可选值,不应包装在可选值中。