我正在处理一个问题,而我的理解在Spring Data JPA上看起来不受支持。
我在视图上有一个网格(使用jQuery的JqGrid插件),它将参数发送到服务器,解析它们,然后执行通过规范生成的动态查询。
当我想订购一个不属于根实体的列时,会出现问题。
EG。交易,卡和账户是我的实体,网格显示last4digits作为用户识别卡的一种方式。你可以想象last4digits属于Card。我查询每个帐户的交易。
使用规范我可以按该属性过滤,连接表等,但排序失败,因为findAll()实现假定Sort类的属性属于根实体。
代码示例:
JQGridRule panFirst6DigitsRule = FilterUtils.findSearchOrFilterRule(settings, Card_.panFirst6Digits.getName());
JQGridRule panLast4DigitsRule = FilterUtils.findSearchOrFilterRule(settings, Card_.panLast4Digits.getName());
if(panFirst6DigitsRule != null) {
filterPan1 = TransactionSpecs.withPanFirst6Digits(panFirst6DigitsRule.getData(),
panFirst6DigitsRule.getOp(), gridGroupOp);
}
if(panLast4DigitsRule != null) {
filterPan2 = TransactionSpecs.withPanLast4Digits(panLast4DigitsRule.getData(),
panLast4DigitsRule.getOp(), gridGroupOp);
}
Specification<Transaction> joinSpec = TransactionSpecs.withAccountId(account.getAccountId());
Specification<Transaction> activeSpec = BaseSpecs.withEntityStatus(true);
Page<Transaction> results = transactionRepository.findAll(
Specifications.where(joinSpec).and(filterSpec).and(filterPan1).and(filterPan2).and(activeSpec), springPageable);
springPageable变量包含以这种方式生成的last4Digits列的排序*:
List<Order> sortOrders = new ArrayList<Order>();
Order sortOrder = new Order(Direction.ASC, "panLast4Digits");
sortOrders.add(sortOrder);
sort = new Sort(sortOrders);
*缺少代码解析参数并创建更多订单对象
有人知道如何对属于父实体/类的属性实现这种排序吗?
提前致谢
Spring-data-jpa版本1.4.3和Hibernate版本4.2.8
修改
显示如何生成panLast4Digits的规范
public static Specification<Transaction> withPanLast4Digits(final String panLast4Digits, final JQGridSearchOp op, final JQGridGroupOp whereOp) {
Specification<Transaction> joinSpec = new Specification<Transaction>() {
@Override
public Predicate toPredicate(Root<Transaction> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Join<Transaction, Card> join = joinCards(root, JoinType.INNER);
return FilterUtils.buildPredicate(cb, join.get(Card_.panLast4Digits), op, panLast4Digits, null, whereOp);
}
};
return joinSpec;
}
private static Join<Transaction, Card> joinCards(Root<Transaction> root, JoinType joinType) {
Join<Transaction, Card> join = getJoin(root, Transaction_.parentCard, joinType);
// only join if not already joined
if (join == null) {
join = root.join(Transaction_.parentCard, joinType);
}
return join;
}
protected static <C, T> Join<C, T> getJoin(Root<C> root, Attribute<? super C, T> attribute, JoinType joinType) {
Set<Join<C, ?>> joins = root.getJoins();
for (Join<C, ?> join : joins) {
if (join.getAttribute().equals(attribute) && join.getJoinType().equals(joinType)) {
return (Join<C, T>) join;
}
}
return null;
}
此外,我已更新到spring-data-jpa 1.6.0和hibernate 4.3.5
答案 0 :(得分:4)
排序属性为"yourChildentity.attribute"
在你的情况下,你可以这样使用PagingAndSortingRepository
:
我们假设您有两个实体:Account
和Card
@Entity
public class Account{
// Autogeneration and Ill just assume that your id is type long
private Long id;
@ManyToOne
@JoinColumn(name="CARD_ID")
private Card creditCard;
//getters and setters
}
@Entity
public class Card{
//Id and other attributes.
private String panLast4Digits;
//getters and Setters
}
存储库界面:
@Repository
public interface AccountRepository extends PagingAndSortingRepository<Account, Long>,
JpaSpecificationExecutor<Account>{
}
服务层:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface AccountService{
//you can specify other arguments the one that you want to filter by
Page<Account> filter(Pageable pageable);
}
服务实施:
@Service
public calss AccountServiceImpl implements AccountService{
@Resource//or @Autowired
private AccountRepository repository;
@Override
public Page<Account> filter(Pageable pageable){
//Filter using Specifications if you have other arguments passed in the signature of the method.
return repository.findAll(pageable);//if you have specifications than return repository.findAll(yourspecification,pageable);
}
现在对服务的调用抛出端点或控制器: 只是一个方法来看看如何排序抛出子实体参数:
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
// method
@Resource
private AccountService service;
public Page<Account> consumeMyService(){
// 0 : for Page 1
// 12 for page size
// Soting throw Child enntiy Account , by attribute panLast4Digits
PageRequest pageable = new PageRequest(0,
12, Direction.ASC, "mycard.panLast4Digits");
Page<Account> service.filter(pageable);
}
您必须通过为存储库接口配置Jpa:repositories
并为服务实现配置context:component-scan
来注册bean
此answer也可能有用。