1
JPAリポジトリで引数として使用するJPA述語を作成して、結合テーブルのフィールドに基づいて結果を返そうとしています。それは実際には何もフィルタリングしません。プライマリテーブルのすべてのオブジェクトを元に戻します。 JPAの基準は、実際のアプリケーションにはさまざまな条件があり、動的なクエリであるため、ジョブの適切なツールのように思えます。リポジトリ、ManyToOneを持つSpring 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:
<[[email protected],
[email protected],
[email protected]]>, mergedContextConfiguration = [[email protected] testClass = JpaDemoApplicationTests, locations = '{}', classes = '{class com.example.jpademo.JpaDemoApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[[[email protected] key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,
java.lang.AssertionError:
Expected size:<1> but was:<3> in:
<[[email protected],
[email protected],
[email protected]]>
私は名前のFooのだろう期待した結果 'FOO 1'