Spring Boot JPA 的问题求助大家!

2019-05-25 15:23:50 +08:00
 hengo

请教大家一个问题,现在有两张表 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 类型。

希望大家指点一下。
4075 次点击
所在节点    编程
10 条回复
leonme
2019-05-25 15:28:55 +08:00
类型不匹配,数据库没有 list 类型,用 json
hengo
2019-05-25 15:36:09 +08:00
@leonme JPA 不能处理 List 类型的是吗?那我用 JPA 也不能传 JSON 进去吧
undeflife
2019-05-25 15:49:45 +08:00
你没有实体类?

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

你上面的逻辑就变成了
a = repository.getOne(id).setOId(oid)
repository.save(domain)
hengo
2019-05-25 16:59:19 +08:00
@undeflife 谢谢,我看到您的第一条回复,然后我自己想了一下,也是通过 save 方法成功了,和您第二条回复的方法是一样的,感谢您的耐心回复,谢谢!
hengo
2019-05-25 16:59:45 +08:00
感谢 V 站的大兄弟们,此贴终结。
DarrenLuo
2019-05-25 17:09:01 +08:00
@undeflife 在 jpa 中如果 get 出来的数据没有断开 session 则不需要 save 方法,set 之后会自动处理的
passerbytiny
2019-05-25 17:42:53 +08:00
@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 中不能有多对多关系,要使用聚合、领域事件等机制来代替。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/567588

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX