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

Spring Boot JPA 的问题求助大家!

  •  
  •   hengo · 22 天前 · 1433 次点击

    请教大家一个问题,现在有两张表 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
        1
    leonme   22 天前 via Android
    类型不匹配,数据库没有 list 类型,用 json
        2
    hengo   22 天前
    @leonme JPA 不能处理 List 类型的是吗?那我用 JPA 也不能传 JSON 进去吧
        3
    undeflife   22 天前   ♥ 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
        4
    hengo   22 天前
    @undeflife 对,表 A 里面我就是这么处理的,中间表表 C 是自动生成的。但是我这样传 list 进 JPA 语句里面就出现了我求助的问题。
        5
    ourslay   22 天前 via iPhone
    用 in 试试
        6
    undeflife   22 天前   ♥ 1
    @hengo 常规做法不是直接通过 Repository 里写 Query 去操作数据库 而是直接操作实体类,再通过 Repository 保存

    你上面的逻辑就变成了
    a = repository.getOne(id).setOId(oid)
    repository.save(domain)
        7
    hengo   22 天前
    @undeflife 谢谢,我看到您的第一条回复,然后我自己想了一下,也是通过 save 方法成功了,和您第二条回复的方法是一样的,感谢您的耐心回复,谢谢!
        8
    hengo   22 天前
    感谢 V 站的大兄弟们,此贴终结。
        9
    DarrenLuo   22 天前 via Android
    @undeflife 在 jpa 中如果 get 出来的数据没有断开 session 则不需要 save 方法,set 之后会自动处理的
        10
    passerbytiny   22 天前   ♥ 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 中不能有多对多关系,要使用聚合、领域事件等机制来代替。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   849 人在线   最高记录 5043   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 18ms · UTC 19:05 · PVG 03:05 · LAX 12:05 · JFK 15:05
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1