请教大家一个问题,现在有两张表 A 和表 B。两张表是多对多的关系。用 JPA 生成的三张表,包括一张中间表表 C。
@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 类型。
希望大家指点一下。
1
leonme 2019-05-25 15:28:55 +08:00 via Android
类型不匹配,数据库没有 list 类型,用 json
|
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 |
4
hengo OP @undeflife 对,表 A 里面我就是这么处理的,中间表表 C 是自动生成的。但是我这样传 list 进 JPA 语句里面就出现了我求助的问题。
|
5
ourslay 2019-05-25 16:11:07 +08:00 via iPhone
用 in 试试
|
6
undeflife 2019-05-25 16:39:15 +08:00 1
@hengo 常规做法不是直接通过 Repository 里写 Query 去操作数据库 而是直接操作实体类,再通过 Repository 保存
你上面的逻辑就变成了 a = repository.getOne(id).setOId(oid) repository.save(domain) |
7
hengo OP @undeflife 谢谢,我看到您的第一条回复,然后我自己想了一下,也是通过 save 方法成功了,和您第二条回复的方法是一样的,感谢您的耐心回复,谢谢!
|
8
hengo OP 感谢 V 站的大兄弟们,此贴终结。
|
9
DarrenLuo 2019-05-25 17:09:01 +08:00 via Android
@undeflife 在 jpa 中如果 get 出来的数据没有断开 session 则不需要 save 方法,set 之后会自动处理的
|
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 中不能有多对多关系,要使用聚合、领域事件等机制来代替。 |