Spring JPA如何查询包含指定brownBearId的Animal实体(子对象为无映射DTO)
可行实现方案
首先明确核心前提:只有Animal是JPA实体,嵌套的Bear、BrownBear等对象均无JPA映射,说明Animal中的bears、dogs集合字段在数据库中是以JSON类型存储的,无需全量查询后内存遍历,可通过数据库原生JSON查询能力结合JPA @Query注解实现,也可兼容小数据量的内存过滤方案。
方案1:基于数据库JSON查询的@Query实现(推荐,性能更高)
根据你使用的数据库选择对应写法:
MySQL 5.7+/8.0 版本
使用JSON_SEARCH函数匹配嵌套数组中的指定brownBearId:
public interface AnimalRepository extends JpaRepository<Animal, String> { @Query(value = "SELECT * FROM animal " + "WHERE JSON_SEARCH(bears, 'one', :targetBrownBearId, null, '$.brownBears[*].brownBearId') IS NOT NULL", nativeQuery = true) List<Animal> findAllByBrownBearId(@Param("targetBrownBearId") String targetBrownBearId); }
PostgreSQL 版本
使用jsonb包含操作符实现匹配:
public interface AnimalRepository extends JpaRepository<Animal, String> { @Query(value = "SELECT * FROM animal " + "WHERE bears::jsonb @> '[{\"brownBears\": [{\"brownBearId\": :targetBrownBearId}]}]'::jsonb", nativeQuery = true) List<Animal> findAllByBrownBearId(@Param("targetBrownBearId") String targetBrownBearId); }
注意:使用该方案需要提前给
Animal的集合字段配置JSON类型处理器,比如Hibernate的@Type(type = "json")注解,保证序列化/反序列化正常。数据量较大时可给JSON字段加对应索引(MySQL的JSON函数索引、PostgreSQL的GIN索引)提升查询性能。
方案2:全量查询后内存过滤(兼容所有数据库,适合小数据量场景)
如果数据量小、或者需要兼容不支持JSON查询的数据库,可以直接查询后通过stream流式过滤:
@Service public class AnimalService { @Autowired private AnimalRepository animalRepository; public List<Animal> findAllByBrownBearId(String targetBrownBearId) { return animalRepository.findAll().stream() // 过滤无bear集合的animal .filter(animal -> animal.getBears() != null && !animal.getBears().isEmpty()) .filter(animal -> animal.getBears().stream() // 过滤无brownBear集合的bear .filter(bear -> bear.getBrownBears() != null && !bear.getBrownBears().isEmpty()) // 匹配目标brownBearId .anyMatch(bear -> bear.getBrownBears().stream() .anyMatch(brownBear -> targetBrownBearId.equals(brownBear.getBrownBearId())) ) ).collect(Collectors.toList()); } }
内容的提问来源于stack exchange,提问作者duppydodah
相关产品推荐
相关产品推荐

