我们在开发中经常出现动态查询,例如淘宝的商品查询,这类查询动态条件,如果用原生的sql语句,很难处理,但是jpa为我们提供的动态查询接口:public interface JpaSpecificationExecutor<T>,这几接口有如下方法:
public interface JpaSpecificationExecutor<T> {
/**
* Returns a single entity matching the given {@link Specification}.
*
* @param spec
* @return
*/
T findOne(Specification<T> spec);
/**
* Returns all entities matching the given {@link Specification}.
*
* @param spec
* @return
*/
List<T> findAll(Specification<T> spec);
/**
* Returns a {@link Page} of entities matching the given {@link Specification}.
*
* @param spec
* @param pageable
* @return
*/
Page<T> findAll(Specification<T> spec, Pageable pageable);
/**
* Returns all entities matching the given {@link Specification} and {@link Sort}.
*
* @param spec
* @param sort
* @return
*/
List<T> findAll(Specification<T> spec, Sort sort);
/**
* Returns the number of instances that the given {@link Specification} will return.
*
* @param spec the {@link Specification} to count instances for
* @return the number of instances
*/
long count(Specification<T> spec);
}
代码实现:
1.先在dao层继承这个接口
public interface UserRepository extends JpaRepository<User, Long> ,JpaSpecificationExecutor<User>{}
2.然后在新建一个Criteria 文件,UserCriteria,代码如下:
public class UserCriteria implements Serializable {
private static final long serialVersionUID = 1L;
private LongFilter id;
private IntegerFilter name;
private IntegerFilter pwd;
//get ...
//set ...
//toSting
}
这里需要注意时间类型不支持Date,其他的都用包装类型
3.service层
@Service
@Transactional
public class UserService {
private final Logger log = LoggerFactory.getLogger(UserService1.class);
@Autowired
private UserRepository userRepository;
public Page<User> findAll(UserCriteria userCriteria,Pageable pageable){
final Specifications<User> specification = createSpecification(userCriteria);
return userRepository.findAll(specification, pageable);
}
public Specifications<User> createSpecification(UserCriteria criteria) {
Specifications<User> specification = Specifications.where(null);
if (criteria != null) {
if (criteria.getId() != null) {
specification = specification.and(buildRangeSpecification(criteria.getId(), User_.id));
}
if (criteria.getName() != null) {
specification = specification.and(buildRangeSpecification(criteria.getName(), User_.name));
}
if (criteria.getPwd() != null) {
specification = specification.and(buildRangeSpecification(criteria.getPwd(), User_.pwd));
}
}
return specification;
}
}
4.web层
@RestController
@RequestMapping("/api")
public class AccountResource {
private final Logger log = LoggerFactory.getLogger(AccountResource.class);
@Autowired
private UserRepository userRepository;
public Object findAll(
UserCriteria criteria,
Pageable pageable
){
return userRepository.findAll(criteria,pageable)
}
}
这样就基本可以了
这里面传值也比较奇葩,传值方式大概有如下: