我尝试创建一个JPA谓词,用作我的JPA存储库中的参数,以便根据连接表中的字段返回结果。它实际上从未过滤任何东西我得到了主表的所有对象。 JPA标准似乎是适合该作业的工具,因为实际应用的应用程序具有许多不同的条件并且是动态查询。
代码:
@Getter
@Setter
@Entity
@Table(name = "FOO")
public class Foo {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(mappedBy = "foo")
private Set<Bar> bars;
}
@Getter
@Setter
@Entity
@Table(name = "BAR")
public class Bar {
@Id
@Column(name="id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
private String name;
@ManyToOne
@JoinColumn(name = "foo_id", nullable = false)
private Foo foo;
}
public class FooSpecs {
public Specification<Foo> barName(String name) {
return (root, query, builder) -> {
Root<Foo> foo = query.distinct(true).from(Foo.class);
Join<Foo, Bar> bar = foo.join("bars", JoinType.LEFT);
Predicate pred = builder.equal(bar.get("name"), name);
return pred;
};
}
}
public interface FooRepository extends JpaRepository<Foo, Integer>, JpaSpecificationExecutor {
}
测试
@RunWith(SpringRunner.class)
@DataJpaTest
@SpringBootTest
public class JpaDemoApplicationTests {
@Autowired
FooRepository repo;
@Test
public void contextLoads() {
FooSpecs specs = new FooSpecs();
Specification<Foo> spec = specs.barName("test 2");
List<Foo> foos = repo.findAll(spec);
// List<Foo> foos = repo.findAll();
assertThat(foos)
.isNotEmpty()
.hasSize(1);
}
}
数据
insert into Foo(id, name) values (1, 'foo 1');
insert into Foo(id, name) values (2, 'foo 2');
insert into Foo(id, name) values (3, 'foo 3');
insert into Bar (id, name, foo_id) values (1, 'test 1', 2);
insert into Bar (id, name, foo_id) values (2, 'test 2', 1);
Hibernate查询输出:
Hibernate: select distinct foo0_.id as id1_1_, foo0_.name as name2_1_ from foo foo0_ cross join foo foo1_ left outer join bar bars2_ on foo1_.id=bars2_.foo_id where bars2_.name=?
我不是最嘻嘻的加入,但是交叉加入似乎不合适,根据我的理解可能是问题的一部分。
测试输出:
Expected size:<1> but was:<3> in:
<[com.example.jpademo.dto.Foo@6e0e5dec,
com.example.jpademo.dto.Foo@56476c16,
com.example.jpademo.dto.Foo@497b560e]>, mergedContextConfiguration = [MergedContextConfiguration@525f1e4e testClass = JpaDemoApplicationTests, locations = '{}', classes = '{class com.example.jpademo.JpaDemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@75f9eccc key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,
java.lang.AssertionError:
Expected size:<1> but was:<3> in:
<[com.example.jpademo.dto.Foo@6e0e5dec,
com.example.jpademo.dto.Foo@56476c16,
com.example.jpademo.dto.Foo@497b560e]>
我期望的结果是Foo of name&#39; foo 1&#39;
答案 0 :(得分:0)
public class FooSpecs {
public Specification<Foo> barName(String name) {
return (root, query, builder) -> {
Join<Foo, Bar> bar = root.join("bars");
Predicate pred = builder.equal(bar.get("name"), name);
return pred;
};
}
}