2017-07-26 27 views
0

所以我使用spring数据,并且遇到了一个问题,试图为此hibernate查询返回一个列表。Spring Data创建内部联接OneToMany

interface NewFooWithMetadataDAO : Repository<Foo, Int> { 
    @Query("""SELECT NEW com.foo.persistence.sql.po.NewFooWithMetadataPO(
        b.id, 
        b.accountId, 
        bi.profitCenterSegmentation, 
        b.fooContext 
       ) 
       from 
        Foo b 
        left join b.fooIntent bi 
        left join b.fooContext bc 
       where 
        account_id = ?1 
       group by 
        b.id 
    """) 
    fun findByAccountId(accountId: Int): List<NewFooWithMetadataPO> 
} 

这个查询创建一个这样的hibernate查询。

select 
    foo0_.id as col_0_0_, 
    foo0_.account_id as col_1_0_, 
    foo_buc1_.profit_center_segmentation as col_2_0_, 
    . as col_3_0_ 
from 
    foo foo0_ 
    left outer join foo_intent foo_buc1_ on foo0_.foo_intent_id=foo_buc1_.id 
    left outer join foo_context_map foocont2_ on foo0_.id=foocont2_.foo_id 
    inner join foo_context_map foocont3_ on foo0_.id=foocont3_.foo_id 
where 
    account_id=? 
group by foo0_.id 

这是一个错误的查询。

我也尝试过bc而不是b.fooContext在HQL中,但后来我没有收到一个集合,我得到一个FooContextPO。

我的实体都喜欢

@Entity 
@Table(name = "foo") 
data class Foo(
     @Id 
     val id: Int, 
     @Column(name= "account_id") 
     val accountId: Int, 

     @OneToOne 
     @JoinColumn(name = "foo_intent_id", referencedColumnName = "id") 
     @NotFound(action=NotFoundAction.IGNORE) 
     val fooIntent: FooIntentPO, 


     @OneToMany 
     @JoinColumn(name = "foo_id", referencedColumnName = "id") 
     @NotFound(action=NotFoundAction.IGNORE) 
     val fooContext: Collection<FooContextPO> 
){ 
     @Entity 
     @Table(name = "foo_intent") 
     data class FooIntentPO(
       @Id 
       val id: Int, 
       @Column(name = "profit_center_segmentation") 
       val profitCenterSegmentation: String 
     ) 
     @Entity 
     @Table(name = "foo_context_map") 
     data class FooContextPO(
       @Id 
       val id: Int, 
       @Column(name = "foo_id") 
       val fooId: Int, 
       @OneToOne 
       @JoinColumn(name = "context_id", referencedColumnName = "id") 
       val context: ContextPO 
     ) 
     @Entity 
     @Table(name = "context") 
     data class ContextPO (
       @Id 
       val id: Int, 
       @ManyToOne 
       @JoinColumn(name = "foo_id", referencedColumnName = "id") 
       val foo: Foo, 
       @Column(name = "context") 
       val context: String 
     ) 

} 

data class NewFooWithMetadataPO(
     val id: Int, 
     val accountId: Int?, 
     val profitCenterSegmentation: String?, 
     val context: Collection<Foo.FooContextPO> 
) 

是否有某种方式,我得到了LEFT JOIN正确这里没有它产生内部联接工作?

回答

0

你肯定得到内部联接由于选择下面

SELECT NEW com.foo.persistence.sql.po.NewFooWithMetadataPO(
        b.id, 
        b.accountId, 
        bi.profitCenterSegmentation, 
        b.fooContext 
       )... 

你独立外侧连接到FooContextPO作为bc所以对应的属性b.fooContext如果你想避免内部联接,你无法引用映射的属性fooContext。所以你需要选择bc

由于实际的底层数据,您是否仅获得1条记录?当您选择bc而不是b.fooContext时,生成的SQL是否也不正确?如果是这样的话......你能分享一下那个sql的样子吗?