使用规范按父实体排序

Ped*_*les 1 java sql hibernate jpa spring-data-jpa

我正在处理一个我认为无法在Spring Data JPA上支持的问题。

我在视图上得到一个网格(使用jQuery的JqGrid插件),该网格将参数发送到服务器,对其进行解析,然后执行通过Specification生成的动态查询。

当我要订购不属于根实体的列时,问题就来了。

例如。交易,卡和帐户是我的实体,网格显示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);
Run Code Online (Sandbox Code Playgroud)

springPageable变量包含以这种方式生成的Sort for last4Digits列*:

List<Order> sortOrders = new ArrayList<Order>();
Order sortOrder = new Order(Direction.ASC, "panLast4Digits");
sortOrders.add(sortOrder);
sort = new Sort(sortOrders);
Run Code Online (Sandbox Code Playgroud)

*缺少代码解析参数,无法创建更多Order对象

有人知道如何对属于父实体/类的属性实施这种排序吗?

提前致谢

用于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;
}
Run Code Online (Sandbox Code Playgroud)

另外我已经更新到spring-data-jpa 1.6.0和hibernate 4.3.5

Raf*_*LDI 5

排序的属性是 "yourChildentity.attribute"

在您的案例中,您可以使用PagingAndSortingRepository以下方式:

假设您有两个实体:an Account和aCard

@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
}
Run Code Online (Sandbox Code Playgroud)

仓库接口:

@Repository
public interface AccountRepository extends PagingAndSortingRepository<Account, Long>,
        JpaSpecificationExecutor<Account>{
}
Run Code Online (Sandbox Code Playgroud)

服务层:

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);
}
Run Code Online (Sandbox Code Playgroud)

服务实施:

 @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); 
}
Run Code Online (Sandbox Code Playgroud)

现在,对服务的调用将引发端点或控制器:仅是一种方法,以了解如何对throw子实体参数进行排序:

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);
}
Run Code Online (Sandbox Code Playgroud)

您必须通过配置Jpa:repositories存储库接口和context:component-scan服务实现来注册Bean。

这个 答案也可能有用。