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

如何通过JPA自定义查询获取包含指定ID的MyEntity实体

解决方法

方案1:带边界处理的原生SQL查询

直接在Repository接口中定义带原生SQL的查询方法,同时解决LIKE的误匹配问题:

@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
    @Query(value = "SELECT * FROM my_entity WHERE CONCAT(',', ids, ',') LIKE CONCAT('%,', :targetId, ',%')", nativeQuery = true)
    List<MyEntity> findByIdsContaining(@Param("targetId") String targetId);
}

通过给存储的逗号分隔字符串前后拼接逗号,把1,2,3转为,1,2,3,,再匹配,1,这种格式,能精准定位单个ID,避免误匹配11这类包含目标ID的字符串。

方案2:JPA Criteria API构建查询

如果偏好面向对象的查询方式,用Criteria API实现相同逻辑:

@Service
public class MyEntityService {
    @Autowired
    private EntityManager entityManager;

    public List<MyEntity> findBySpecificId(String targetId) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<MyEntity> query = cb.createQuery(MyEntity.class);
        Root<MyEntity> root = query.from(MyEntity.class);

        // 构造包裹后的字段和匹配模式
        Expression<String> wrappedIds = cb.concat(cb.concat(cb.literal(","), root.get("ids")), cb.literal(","));
        Expression<String> matchPattern = cb.concat(cb.concat(cb.literal("%,"), cb.literal(targetId)), cb.literal(",%"));
        Predicate matchCondition = cb.like(wrappedIds, matchPattern);

        query.select(root).where(matchCondition);
        return entityManager.createQuery(query).getResultList();
    }
}

方案3:JPQL形式的查询

也可以用JPQL替代原生SQL,直接引用实体字段,JPA会自动映射到数据库列:

@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
    @Query("SELECT me FROM MyEntity me WHERE CONCAT(',', me.ids, ',') LIKE CONCAT('%,', :targetId, ',%')")
    List<MyEntity> findByIdsContainingJpql(@Param("targetId") String targetId);
}

这种方式不用写原生表名和列名,更符合JPA的ORM风格。

注意事项

直接用LIKE '%1%'会存在误匹配问题,比如会把包含11的记录也查出来,所以必须通过前后拼接逗号的方式确保匹配的是完整的单个ID。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:10:46