V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yumc
V2EX  ›  Java

关于 spring data jpa 的一些业务问题

  •  
  •   yumc · 2020-06-11 00:23:20 +08:00 · 2294 次点击
    这是一个创建于 498 天前的主题,其中的信息可能已经有所发展或是发生改变。

    1.多条件动态查询如何实现呢?
    目前是使用 @Query 写原生 SQL,通过 IF 表达式实现,SQL 非常臃肿并且存在两个小问题。
    还望各位前辈指导。
    2.更新操作目前解决方案是通过先查询,再赋值,最后使用 save 方法更新,这样做是不是不合适呢? 我看过相关博客文章,有提到重写 jpa 的 save 方法可以做饭动态更新(不更空属性),接下来我会尝试一下。
    请问各位大佬有没有更成熟的 jpa 多条件动态查询 和动态更新的解决方案呢,非常感谢各位的建议。

    17 条回复    2020-06-11 14:34:27 +08:00
    njshiyanhz
        1
    njshiyanhz   2020-06-11 00:35:08 +08:00 via Android
    querydsl
    bxb100
        2
    bxb100   2020-06-11 02:12:21 +08:00 via Android
    2 挺合适
    zhazi
        3
    zhazi   2020-06-11 02:15:58 +08:00   ❤️ 1
    voidxx
        4
    voidxx   2020-06-11 08:37:47 +08:00
    站内搜索 [querydsl]
    hantsy
        5
    hantsy   2020-06-11 08:46:33 +08:00
    1. Spring Data JPA 集成了多种方法,这些只要看了文档就不会有疑问了。
    a 基于 Certeria API 的 Specification
    b Query By Example
    cQueryDSL
    https://github.com/hantsy/spring4-sandbox/tree/master/data-jpa/src/main/java/com/hantsylabs/example/spring/jpa

    基于字符拼接的查询方式这几年几乎不用,好几个项目中明文要求是不允许用,国内只管结果的, 当然很少公司有代码洁癖,很少讲 Typesafe 的。另外如果能够做 Typesafe 的还 JOOQ 代替 Jdbc SQL 的语句。


    2.本来就应该这样用
    damai0419
        6
    damai0419   2020-06-11 09:11:06 +08:00
    1 、querydsl
    2 、合适
    Ico945
        7
    Ico945   2020-06-11 09:52:56 +08:00
    刚好新接触一个项目是 JPA 的,用 querydsl 很方便,可以把条件放到一个数组里然后执行 sql 操作就不显臃肿;查询更新再赋值好多都是这么做的- -
    EastLord
        8
    EastLord   2020-06-11 10:18:54 +08:00
    2.更新操作可以不用 save
    caotian
        9
    caotian   2020-06-11 10:47:21 +08:00
    1. specification
    2. json patch
    cnwlei
        10
    cnwlei   2020-06-11 11:43:04 +08:00
    query.where(cb.and(ps.toArray(new Predicate[ps.size()])));
    yumc
        11
    yumc   2020-06-11 13:25:58 +08:00
    谢谢各位的解答。
    我在周末会详细的分析学习以下,非常感谢😘
    hantsy
        12
    hantsy   2020-06-11 13:46:51 +08:00
    @EastLord 嗯,Hibernate 中在一个 Session 生命周期内, 状态的修改,在 flush 时(事务会触发)自动同步到数据库。Hibernate 以前在 Seam 最常用的一种方式,是手动 Flush,在一个 Conversation 内,多次修改(比如多步提交),最后提交手动 Flush 才同步到数据库。
    Cowhitewhite
        13
    Cowhitewhite   2020-06-11 13:49:38 +08:00
    哈哈 我之前都是?1 ?2 ?3
    lickysee
        15
    lickysee   2020-06-11 14:24:50 +08:00
    提供一个自己的思路,代码仅供参考,希望对你有帮助。
    ```
    public class SpecificationUtil {

    public static <T> Specification<T> stringLike(
    final String field,
    final String param
    ) {
    return skipNullAndBlank(
    param,
    (builder, root) -> builder.like(root.get(field), "%" + param + "%")
    );
    }


    private static <T> Specification<T> skipNullAndBlank(
    String p,
    BiFunction<CriteriaBuilder, Root<T>, Predicate> f
    ) {
    return ((Specification<T>) (root, query, builder) -> {
    if (Strings.isBlank(p)) {
    return query.getGroupRestriction();
    } else {
    return f.apply(builder, root);
    }
    });
    }
    }
    ```
    lickysee
        16
    lickysee   2020-06-11 14:28:19 +08:00
    大致上的思路就是将判断如果是空就不进行查询这种重复的代码提取出来,返回一个 Specification,然后结合官方给出来的例子,进行条件的拼接。

    参照官方文档 Example 98. Combined Specifications
    wysnylc
        17
    wysnylc   2020-06-11 14:34:27 +08:00
    不要用注解写 sql,维护起来很麻烦
    先查询后更新有并发问题记得加锁,有事务也有并发问题不要觉得加了事务就万无一失
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4073 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 03:02 · PVG 11:02 · LAX 20:02 · JFK 23:02
    ♥ Do have faith in what you're doing.