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

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

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

    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  
    OP
       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,维护起来很麻烦
    先查询后更新有并发问题记得加锁,有事务也有并发问题不要觉得加了事务就万无一失
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3312 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:49 · PVG 08:49 · LAX 16:49 · JFK 19:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.