OneToOne JPA / Hibernate eager loading cause N+1 select
Posted
by
Alexandre Lavoie
on Stack Overflow
See other posts from Stack Overflow
or by Alexandre Lavoie
Published on 2014-06-06T07:36:28Z
Indexed on
2014/06/10
9:25 UTC
Read the original article
Hit count: 352
I created a method to have multilingual text on different objects without creating field for each languages or tables for each objects types.
Now the only problem I've got is N+1 select queries when doing a simple loading.
Tables schema :
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;
}
}
And it is used like this on a object (having a foreign key to the multilingual text) :
@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;
}
}
Now, when doing a simple HQL query : from TestEntity
, I get a query selecting TestEntity
's and one query for each MultilingualText
that need to be loaded on each TestEntity
. I've searched a lot and found absolutely no solutions. I have tested :
@Fetch(FetchType.JOIN)
optional = false
@ManyToOne
instead of@OneToOne
Now I am out of idea!
© Stack Overflow or respective owner