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);
}
}
编辑:
由于Organization
到Teams
是一对多关系,按理说如果没有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 书中指出:容器类型,包括集合、映射、流、数组和可选值,不应包装在可选值中。
我有以下两个实体:
@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);
}
}
编辑:
由于Organization
到Teams
是一对多关系,按理说如果没有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 书中指出:容器类型,包括集合、映射、流、数组和可选值,不应包装在可选值中。