基于JPA(EclipseLink)和Spring Data按列对查询MSSQL表行
问题描述
现有MSSQL表t1,结构及数据如下:
create table t1 ( id int IDENTITY(1,1), col1 int not null, col2 int not null, constraint t1_UK UNIQUE (col1, col2) )
表中数据:
id col1 col2 1 25 661 2 25 741 3 89 661 4 89 741
对应的JPA实体类T1Entity定义:
@Entity @Table class T1Entity { @Id @GeneratedValue private int id; @Column private int col1; @Column private int col2; // getters, setters }
需求:查询id为1和4的行,仅通过col1和col2作为查询条件。注意使用findByCol1InAndCol2In(List.of(25, 89), List.of(661, 741))会返回所有样本数据,不符合需求,需实现类似SELECT col1, col2 from t1 where (col1=25 and col2 = 661) OR (col1=89 and col2=741)的查询效果。
解决方案
一、Spring Data JPA结合EclipseLink实现方式
1. 自定义JPQL查询(静态多组条件)
在Repository接口中直接编写JPQL语句,明确指定每组col1+col2的匹配条件:
public interface T1EntityRepository extends JpaRepository<T1Entity, Integer> { @Query("SELECT t FROM T1Entity t WHERE (t.col1 = :col1a AND t.col2 = :col2a) OR (t.col1 = :col1b AND t.col2 = :col2b)") List<T1Entity> findBySpecifiedColPairs( @Param("col1a") int col1a, @Param("col2a") int col2a, @Param("col1b") int col1b, @Param("col2b") int col2b ); }
调用时传入对应参数即可:
List<T1Entity> result = repository.findBySpecifiedColPairs(25, 661, 89, 741);
2. 动态行值IN查询(支持任意多组条件)
利用JPQL的行值表达式特性,直接传入多组col1+col2的配对列表,EclipseLink完全支持这种语法:
public interface T1EntityRepository extends JpaRepository<T1Entity, Integer> { @Query("SELECT t FROM T1Entity t WHERE (t.col1, t.col2) IN :pairs") List<T1Entity> findByColPairs(@Param("pairs") List<Object[]> pairs); }
调用时构造配对列表:
List<Object[]> pairs = Arrays.asList( new Object[]{25, 661}, new Object[]{89, 741} ); List<T1Entity> result = repository.findByColPairs(pairs);
3. 使用Specification动态构建查询
如果需要更灵活的动态条件拼接,可以借助JpaSpecificationExecutor:
首先扩展Repository接口:
public interface T1EntityRepository extends JpaRepository<T1Entity, Integer>, JpaSpecificationExecutor<T1Entity> { }
然后构建查询条件并执行:
Specification<T1Entity> spec = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); // 添加每组col1+col2的匹配条件 predicates.add(cb.and(cb.equal(root.get("col1"), 25), cb.equal(root.get("col2"), 661))); predicates.add(cb.and(cb.equal(root.get("col1"), 89), cb.equal(root.get("col2"), 741))); // 用OR拼接所有条件 return cb.or(predicates.toArray(new Predicate[0])); }; List<T1Entity> result = repository.findAll(spec);
二、SQL的替代写法(无需OR嵌套AND)
1. 行值构造器IN语法
MSSQL支持直接使用行值的IN匹配,语法简洁:
SELECT id, col1, col2 FROM t1 WHERE (col1, col2) IN ((25, 661), (89, 741));
2. JOIN临时表方式
通过JOIN一个包含目标配对的临时表来实现查询,适合复杂场景:
SELECT t.id, t.col1, t.col2 FROM t1 t JOIN ( VALUES (25, 661), (89, 741) ) AS temp(c1, c2) ON t.col1 = temp.c1 AND t.col2 = temp.c2;
内容的提问来源于stack exchange,提问作者SJ1
相关产品推荐
相关产品推荐

