如何编写Jpa规范来连接两个表?

时间:2018-03-27 03:47:15

标签: java spring hibernate spring-data-jpa criteria

说我有两个实体如下:

@Data
@Entity
@Table(name = "reward")   
public class Reward{

  @Id
  @GeneratedValue(generator = "system-uuid")
  @GenericGenerator(name = "system-uuid", strategy = "org.hibernate.id.UUIDGenerator")
  @Column(length = 36)
  private String id;

  private String sn;

  //other fields

}


@Data
@Entity
@Table(name = "strategy_rewards")
public class RewardUserRelation{

  @Id
  @GeneratedValue(generator = "system-uuid")
  @GenericGenerator(name = "system-uuid", strategy = "org.hibernate.id.UUIDGenerator")
  @Column(length = 36)  
  private String id; 

  private String uid;

  private String rid; //reward id

  //other fields;    

}

我已经编写了一些其他规范,如下所示,从mysql中过滤我的奖励数据并将其返回给其他服务:

public static Specification<Reward> withSn(String sn) {
    return (root, query, builder) -> builder
        .like(root.get("sn"), "%" +sn + "%");
  }

Page result = rewardRepository.findAll(where(sn == null ? null : 
    RewardSpecs.withSn(sn)), pageable));

但现在我想完成一个规范,该规范可以过滤其ID未出现在RewardUserRelation表中的奖励,这意味着这些奖励未被使用。我已经搜索了几个规范教程,但仍然无法解决。我应该使用Join Criteria Api吗?但我不知道该怎么做。 :(

更新:不知何故,我设法通过事先从关系表中选择所有并使用Expression.in()来解决这个问题,但仍然想知道是否有更好的方法来执行此操作。

List<String> idList =strategyRewardRelationRepository.getByDeleted(false).stream()
.map(StrategyRewardRelation::getRid).distinct().collect(Collectors.toList());

public static Specification<Reward> withUsed(Boolean used, List<String> idList) {
    return (root, query, builder) -> {
      return used ? root.get("id").in(idList) : root.get("id").in(idList).not();
    };
 }

1 个答案:

答案 0 :(得分:0)

Specification中的两次联接可能是解决方法:

case "propertyId":
                Join<SourceEntity, Item> itemJoin = root.join("item");
                Join<SourceEntity, ItemSourceDetail> itemDetailJoin = itemJoin.join("itemSourceDetail");
                try {
                    filterValue = criteria.getString(key).toString();
                    filters.add(itemDetailJoin.get("propertyId").in(Long.valueOf(filterValue)));
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;