我有两张tableA和B。
@Table(name = "table_a")
@Data
public class A {
@Column(name = "id")
private Integer id;
@OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
private List<B> bs;
}
@Table(name = "table_b")
@Data
public class B {
@Column(name = "id")
private Integer b_id;
@Column(name = "a_id)
private Integer a_id;
@Column(name = "status")
private Integer status;
@ManyToOne
@JoinColumn(name = "a_id", insertable = false, updatable = false)
private A a;
}
字符串
现在的问题是,当我尝试运行下面这个查询的JPQL版本时,
select a.* from table_a a
inner join table_b b on a.id = b.a_id
where b.status = -1;
型
它返回所有行,即使状态不是-1,即它返回table_b中与table a的id相关联的所有行。我知道我使用它不正确,我应该怎么做才能查询table_b中存在的状态
1条答案
按热度按时间oknrviil1#
我建了一个复制器,它是available at
github.com
。技术清理
在此期间,我注意到以下几点:
1.实体
A
和B
缺少@Entitiy
-注解1.实体
A
和B
在主键上缺少@Id
注解1.实体
B
中的属性a_id
是多余的这导致实体
A
和B
的以下重构:A.java
:字符串
B.java
:型
查询构造
有了这些变化,我们就可以解决实际问题了。JPQL(
jakarta.ee
)中join的语法如下:型
翻译成我们的例子,这导致
型
注意,我们写了
a.bs b
。我们访问一个集合,但将其命名为singular。从查询的Angular 来看,该集合对我们来说是透明的,我们只能看到单数B
-实体(想象查询是一个循环,对bs
中的每个B
执行)。有了这些知识,我们可以用公式表示
WHERE
条件,然后简单明了:型
我们现在可以在
ARepository
中定义这个查询:型
测试
使用
Controller.java
访问实体:型
一些测试数据:
型
我们现在可以运行
./mvnw clean package
来运行集成测试:ControllerTest.java
:型
注意,集成测试使用了testcontainers,因此需要一个与docker或docker兼容的环境来执行。
备注
我将database-entity 1:1传播到rest-endpoint。这样做是为了简洁。特别注意,我必须在
A
中@JsonIgnore
bs
。如果我们不这样做,Jackson将由于双向关系而陷入无限递归。对于生产级解决方案,我建议隔离数据库和响应实体。