Hibernate对@OneToOne连接进行多次查询

时间:2015-11-17 11:17:07

标签: hibernate jpa

我正在使用Hibernate 3.6.10.Final和我在Java 1.6上。

结构:

@Entity
class Test
{
    @Id
    private String id;

    @OneToOne(mappedBy = "test")
    private Test_Team test_team;
}
@Entity
class Test_Team
{

    @Id
    private long id;

    @OneToOne
    @JoinColumn(name = "TEST_ID", referencedColumnName = "ID", insertable = false, updatable = false)
    private Test test;

    @OneToOne
    @JoinColumn(name="TEAM_ID", referencedColumnName="ID", insertable=false, updatable=false)
    private Team team;
}
class Team
{
    @Id
    private long id;

    @OneToOne(mappedBy="team")
    private Test_Team test_team;
}

Hibernate生成的SQL:

SELECT * 
FROM   (SELECT test0_.id
        FROM   test test0_ ) 
WHERE  rownum <= 1 // LIMIT 1
SELECT test_team0_.id,                     
       test_team0_.team_id,                  
       test_team0_.test_id,
       team1_.id,
       test2_.id,
FROM   test_team test_team0_ 
       LEFT OUTER JOIN team team1_ 
                    ON test_team0.team_id = team1_.id 
       LEFT OUTER JOIN test test2_ 
                    ON test_team0_.test_id = test2_.id
WHERE  test_team_.test_id = ? 
SELECT test_team0_.id, 
       test_team0.team_id,
       test_team0.test_id,
       team1_.id,                      
       test2_.id,
FROM   test_team test_team0_
       LEFT OUTER JOIN team team1_ 
                    ON test_team0_.team_id = team1_.id 
       LEFT OUTER JOIN test test2_ 
                    ON test_team0_.test_id = test2_.id
WHERE  test_team0_.team_id = ? 

当我对TEST进行选择时,Hibernate会在TEST_TEAMTEAM上进行N次查询。

如何避免这种情况或如何减少查询量?但是,加载时需要所有数据。

2 个答案:

答案 0 :(得分:0)

这是一个获取问题。你的关系有一个FetchType.EAGER所以Hibernate会加载所选模型的所有关系。您可以切换到FetchType.LAZY以避免所有连接,但并不总是一个不错的选择。

所以你的关系将成为:

@OneToOne
@JoinColumn(name="TEAM_ID", referencedColumnName="ID", insertable=false, updatable=false)
@OneToOne(fetch = FetchType.LAZY, targetEntity = Team.class)
private Team team;

关于 EAGER LAZY fetch之间的区别,请查看this question,并在google上查看一些教程,以实现目标。< / p>

答案 1 :(得分:0)

解决方案是抛弃连接表并在Test&lt;&gt;之间进行直接引用。球队。

您看到的SQL很有意义,因为Hibernate无法知道TestTeam将与Test和Team引用的实体相同。

Test test = .../
test.getTestTeam();//triggers load **where test_id = test.id**
Team team = test.getTestTeam().getTeam();
team.getTestTeam();// triggers load **where team_id = team.id**