OneToOne JPA / Hibernate急切加载导致N + 1选择

时间:2014-06-06 07:36:29

标签: hibernate jpa one-to-one

我创建了一个方法,在不同的对象上使用多语言文本,而不为每种对象类型的每种语言或表创建字段。

现在我唯一遇到的问题是在进行简单加载时N + 1选择查询。

表架构:

CREATE TABLE `testentities` (
  `keyTestEntity` int(11) NOT NULL,
  `keyMultilingualText` int(11) NOT NULL,
  PRIMARY KEY  (`keyTestEntity`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

CREATE TABLE `common_multilingualtexts` (
  `keyMultilingualText` int(11) NOT NULL auto_increment,
  PRIMARY KEY  (`keyMultilingualText`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

CREATE TABLE `common_multilingualtexts_values` (
  `languageCode` varchar(5) NOT NULL,
  `keyMultilingualText` int(11) NOT NULL,
  `value` text,
  PRIMARY KEY  (`languageCode`,`keyMultilingualText`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

MultilingualText.java

@Entity
@Table(name = "common_multilingualtexts")
public class MultilingualText implements Serializable
{
    private Integer m_iKeyMultilingualText;
    private Map<String, String> m_lValues = new HashMap<String, String>();

    public void setKeyMultilingualText(Integer p_iKeyMultilingualText)
    {
        m_iKeyMultilingualText = p_iKeyMultilingualText;
    }

    @Id
    @GeneratedValue
    @Column(name = "keyMultilingualText")
    public Integer getKeyMultilingualText()
    {
        return m_iKeyMultilingualText;
    }

    public void setValues(Map<String, String> p_lValues)
    {
        m_lValues = p_lValues;
    }

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "common_multilingualtexts_values", joinColumns = @JoinColumn(name = "keyMultilingualText"))
    @MapKeyColumn(name = "languageCode")
    @Column(name = "value")
    public Map<String, String> getValues()
    {
        return m_lValues;
    }

    public void put(String p_sLanguageCode, String p_sValue)
    {
        m_lValues.put(p_sLanguageCode,p_sValue);
    }

    public String get(String p_sLanguageCode)
    {
        if(m_lValues.containsKey(p_sLanguageCode))
        {
            return m_lValues.get(p_sLanguageCode);
        }

        return null;
    }
}

它在对象上使用(具有多语言文本的外键):

@Entity
@Table(name = "testentities")
public class TestEntity implements Serializable
{
    private Integer m_iKeyEntity;
    private MultilingualText m_oText;

    public void setKeyEntity(Integer p_iKeyEntity)
    {
        m_iKeyEntity = p_iKeyEntity;
    }

    @Id
    @GeneratedValue
    @Column(name = "keyEntity")
    public Integer getKeyEntity()
    {
        return m_iKeyEntity;
    }


    public void setText(MultilingualText p_oText)
    {
        m_oText = p_oText;
    }

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "keyText")
    public MultilingualText getText()
    {
        return m_oText;
    }
}

现在,在进行简单的HQL查询时from TestEntity,我得到一个查询选择TestEntity,每个MultilingualText需要加载一个查询TestEntity }}。我搜索了很多,发现绝对没有解决方案。我测试过:

  • @Fetch(FetchType.JOIN)
  • optional = false
  • @ManyToOne代替@OneToOne

现在我不在乎了!

修改:

我使用Hibernate 4.2.13

1 个答案:

答案 0 :(得分:2)

尝试这些注释:

@Fetch(FetchMode.SELECT)
@BatchSize(size = 10)

此外,您始终可以LEFT JOIN FETCH,这是与您的特定问题(一对一)的实现无关的解决方案:

SELECT e1 From entity1 e1 LEFT JOIN FETCH e1.oneToOneRel e2 WHERE...