hibernate示例_Spring Jpa Specification 使用示例

spring data jpa为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询。JpaSpecification查询的关键在于怎么构建Predicates。

下面通过示例对其进行学习。

由运动员表(player)和助手表(assistant)表,它们的关系未一对多,即一个运动员可以有多个助手,一个助手只能服务一个运动员。

94a4c399ca0ddb30f58c2fc9852aad05.png

对应实体类如下:

PlayerEntity:

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "player")
public class PlayerEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 国籍
    private String country;

    // 运动员姓名
    private String name;

    // 运动种类
    private String profession;

    // 获得金牌次数
    private int goldenNum;

    // 是否决定参加奥运会
    private boolean attend;

    @OneToMany(targetEntity = AssistantEntity.class)
    @org.hibernate.annotations.ForeignKey(name = "none")
    @JoinColumn(name = "player_assistant", referencedColumnName = "name")
    private List<AssistantEntity> list;
}

AssistantEntity:

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "assistant")
public class AssistantEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 助理名称
    private String name;

    // 助理年龄
    private int age;
}

数据库已有数据情况如下:

57567b439296e043e78ebc25b5338867.png
player表

c8c469949646ad586fd253bb28ba2267.png
assistant表

① 使用and和or的简单复合查询

我们此处查询player,故有PlayerRepo

PlayerRepo:

@Repository
public interface PlayerRepo extends JpaRepository<PlayerEntity, Long>, JpaSpecificationExecutor {
}

Controller代码(按照代码规范,不应在Controller层写业务逻辑代码,此处为了方便展示,将业务逻辑代码写在Controller方法中)

@GetMapping("/jpatest7")
public List<PlayerEntity> jpatest7() {
    Specification spec = (Specification) (root, criteriaQuery, criteriaBuilder) -> {
        List<Predicate> predicates = new ArrayList<>();
        Predicate countryPredicate = criteriaBuilder.equal(root.get("country"), "中国");
        Predicate professionPredicate = criteriaBuilder.equal(root.get("profession"), "篮球");
        Predicate goldenPredicate = criteriaBuilder.equal(root.get("goldenNum"), 5);
        predicates.add(countryPredicate);
        predicates.add(professionPredicate);
        predicates.add(goldenPredicate);
        return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
    };
    List<PlayerEntity> list = playerRepo.findAll(spec);
    return list;
}

记得注入playerRepo。

root.get("country"),对应着实体类的相关属性country,root.get属性对应的实体类,我认为从使用该spec的Repository对应的实体类相对应,比如此处的playerRepo对应的实体类PlayerEntity,实际上如果属性对不上,运行时会报错。root.get取得相应实体的操作字段。

而criteriaBuilder.equal和criteriaBuilder.and,则是用来构建复杂查询

此处示例对应的sql语句为:

select * from player where country = "中国" and profession = "篮球" and golden_num = 5;

Specification查询中用实体类属性,sql语句中用数据库字段。

访问接口结果如下:

ca0deb15c73724c0d24a58e81eb2d868.png

修改

return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));

return criteriaBuilder.or(predicates.toArray(new Predicate[predicates.size()]));

此时对应的sql语句为select * from player where country = "中国" or profession = "篮球" or golden_num = 5;

表中所有数据都复合条件,都查出来,访问结果为:

2f832b7cd64f8dc05886ca1d1a49f2a1.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值