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

Spring Boot JPA 的问题求助大家!

  •  
  •   hengo · 2019-05-25 15:23:50 +08:00 · 4154 次点击
    这是一个创建于 1991 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请教大家一个问题,现在有两张表 A 和表 B。两张表是多对多的关系。用 JPA 生成的三张表,包括一张中间表表 C。

    1. 表 A 现在是维护方,表 B 是被维护方。
    2. 现在更新表 A 的信息,不更新表 B 的信息,但是中间表要更新关联多个表 B 的主键 id,因为一个表 A 关联多张表 B。
    @Modifying
    @Query("update A a SET a.oid = ?1, a.BList = ?2 where a.id = ?3")
    Integer update(String oid, List<B> bList, String id);
    

    我做单元测试,传进去的参数包括一个 List 类型,但是一直提示

        Caused by: java.lang.IllegalArgumentException: Parameter value [bList] did not match expected type [java.util.Collection (n/a)]	
       
    
    
    我知道报错是因为类型不匹配,但是类型应该是匹配的,不知道怎么处理 JPA 的 SQL 语句?可能我这种写法有问题,或者参数根本就不支持 List 类型。
    
    希望大家指点一下。
    
    10 条回复    2019-05-25 17:42:53 +08:00
    leonme
        1
    leonme  
       2019-05-25 15:28:55 +08:00 via Android
    类型不匹配,数据库没有 list 类型,用 json
    hengo
        2
    hengo  
    OP
       2019-05-25 15:36:09 +08:00
    @leonme JPA 不能处理 List 类型的是吗?那我用 JPA 也不能传 JSON 进去吧
    undeflife
        3
    undeflife  
       2019-05-25 15:49:45 +08:00   ❤️ 1
    你没有实体类?

    class A{
    @ManyToMany
    @JoinTable(name = "c",
    joinColumns = @JoinColumn(name = "a_id", referencedColumnName = "id"),
    inverseJoinColumns = @JoinColumn(name = "b_id", referencedColumnName = "id"))
    private Set<B> bs= new HashSet<>();
    }

    中间表自动维护

    JPA
    hengo
        4
    hengo  
    OP
       2019-05-25 15:53:36 +08:00
    @undeflife 对,表 A 里面我就是这么处理的,中间表表 C 是自动生成的。但是我这样传 list 进 JPA 语句里面就出现了我求助的问题。
    ourslay
        5
    ourslay  
       2019-05-25 16:11:07 +08:00 via iPhone
    用 in 试试
    undeflife
        6
    undeflife  
       2019-05-25 16:39:15 +08:00   ❤️ 1
    @hengo 常规做法不是直接通过 Repository 里写 Query 去操作数据库 而是直接操作实体类,再通过 Repository 保存

    你上面的逻辑就变成了
    a = repository.getOne(id).setOId(oid)
    repository.save(domain)
    hengo
        7
    hengo  
    OP
       2019-05-25 16:59:19 +08:00
    @undeflife 谢谢,我看到您的第一条回复,然后我自己想了一下,也是通过 save 方法成功了,和您第二条回复的方法是一样的,感谢您的耐心回复,谢谢!
    hengo
        8
    hengo  
    OP
       2019-05-25 16:59:45 +08:00
    感谢 V 站的大兄弟们,此贴终结。
    DarrenLuo
        9
    DarrenLuo  
       2019-05-25 17:09:01 +08:00 via Android
    @undeflife 在 jpa 中如果 get 出来的数据没有断开 session 则不需要 save 方法,set 之后会自动处理的
    passerbytiny
        10
    passerbytiny  
       2019-05-25 17:42:53 +08:00   ❤️ 1
    @hengo #6 此贴远没有终结
    第一,JPQL、HQL、JDBC 的参数绑定部分,只能绑定特定的类型,包括预定义的和自己注册的。而 List 或者 其他集合类型,通常只能绑定到 “ in ?” ,不能绑定到 “= ?” 。
    第二,@Query 用到的是 JPQL,它并不是完全面向对象的,它解析后对应的是唯一的一条 SQL,而多对多关系的两个实体变更时,要修改 3 个表,需要同时执行 3 条 SQL,是无法通过一个 JPQL 来执行的。所以此时必须使用 save(Entity) 的方式来更新实体。
    第三,@Query 应当只查询,不做增删改,除非你当前的业务不需要考虑实体的同步状态。

    第四,仅在设计思想上相关的:如果只是 JPA,可以使用多对多;如果是 Spring Data JPA (不是 Spring Boot Jpa ),那么不能使用多对多—— Spring Data JPA 的设计基础是领域驱动设计( DDD ),DDD 中不能有多对多关系,要使用聚合、领域事件等机制来代替。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5745 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 01:42 · PVG 09:42 · LAX 17:42 · JFK 20:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.