2017-11-29 4 views
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'

答えて

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; 
     }; 
    } 
} 
関連する問題