2012-07-30 18 views
2

我一直试图找出最后一段时间的这一个结果。与所有那些询问如何仅通过JPA查询得到一个结果的问题完全相反,我需要更多比一个结果 - 我需要所有这些。我最终调用实体管理器的find()方法,但它并没有给我所有的嵌套结果。需要获得来自实体经理的更多结果

'父' 类

@Entity 
@Table(name = "LANGUAGE") 
public class LanguageData extends PersistedAuditedData<Long> { 

@Id 
@Column 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
private Long id; 

@Column(name = "ISO6391ALPHA2CODE") 
private String iso6391Alpha2Code; 

@OneToMany(fetch = FetchType.LAZY, mappedBy = "languageData") 
@MapKeyColumn(name = "LANGUAGE_ID") 
private Map<Long, LanguageDataLocalization> localizations; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "localizationLanguage") 
@MapKeyColumn(name = "LANGUAGE_LOCALIZATION_ID") 
private Map<Long, LanguageDataLocalization> languagesLocalized; 

/** 
* Private no-arg constructor for reflection-based 
    * construction inside JPA providers. 
*/ 
@SuppressWarnings("unused") 
private LanguageData() { 
    // Fields initialized by JPA. 
} 

    // Plus getters for the fields. 

} 

'儿童' 类

@Entity 
@Table(name = "LANGUAGE_LOCALIZATION") 
public class LanguageDataLocalization extends PersistedAuditedData<LanguageLocalizationKey>{ 

@EmbeddedId 
private LanguageLocalizationKey id; 

@Column(name = "REFERENCE_NAME") 
private String name; 

@ManyToOne(fetch = FetchType.EAGER) 
@JoinColumn(name = "LANGUAGE_ID", insertable = false, updatable = false) 
private LanguageData languageData; 

@ManyToOne(fetch = FetchType.EAGER) 
@JoinColumn(name = "LANGUAGE_LOCALIZATION_ID", insertable = false, updatable = false) 
private LanguageData localizationLanguage; 

/** 
* Private no-arg constructor for reflection-based JPA provider instantiation. 
*/ 
@SuppressWarnings("unused") 
private LanguageDataLocalization() { 
    // Fields initialized by JPA. 
} 

    // Plus getters for fields. 
} 

主要用于 '少年' 类。

@Embeddable 
public class LanguageLocalizationKey { 

@Column(name = "LANGUAGE_ID") 
private Long languageId; 

@Column(name = "LANGUAGE_LOCALIZATION_ID") 
private Long languageLocalizationId; 

/** 
* No-arg constructor, for use by JPA provider implementation. 
* <h1>DO NOT USE!</h1> 
* <p>Ideally, this should be <code>private</code>, 
    * however OpenJPA doesn't appear to be allowing that at the moment 
* (unsure of cause). This constructor does not initialize any data.</p> 
*/ 
@SuppressWarnings("unused") 
public LanguageLocalizationKey() { 
    // Field initialization performed by JPA provider. 
} 

    // Plus getters 
} 

而且使用像这样:

@Transactional(readOnly = true, propagation = Propagation.SUPPORTS) 
private Collection<LanguageDataLocalization> getLocalizationsById(final Long id, final Collection<String> localeCodes) { 
    try { 
     if (localeCodes == null || localeCodes.isEmpty()) { 
      final LanguageData data = entityManager.find(LanguageData.class, id); 
      if (data == null) { 
       return Collections.emptyList(); 
      } else { 
       return data.getlocalizations().values(); 
      } 
     } else { 
      List<LanguageDataLocalization> results = entityManager.createNamedQuery("FIND_LANGUAGE_BY_ID", LanguageDataLocalization.class) 
                    .setParameter("iso6391Alpha2Codes", localeCodes) 
                    .setParameter("languageId", id) 
                    .getResultList(); 
      return results; 
     } 
    } catch (NoResultException e) { 
     // TODO: add logging 
     return Collections.emptyList(); 
    } 
} 

随着named-queries.xml定义,像这样:

<?xml version="1.0" encoding="UTF-8"?> 
<entity-mappings version="1.0" 
xmlns="http://java.sun.com/xml/ns/persistence/orm" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm 
        http://java.sun.com/xml/ns/persistence/orm_1_0.xsd "> 

<named-query name="FIND_LANGUAGE_BY_ID"> 
    <query> 
     SELECT localized 
     FROM LanguageDataLocalization localized 
     JOIN localized.localizationLanguage local 
     WHERE localized.id.languageId = :languageId 
     AND local.iso6391Alpha2Code IN :iso6391Alpha2Codes 
    </query> 
</named-query> 
</entity-mappings> 

LANGUAGE数据(德比内存数据库,可以肯定这并不重要):

ID, ISO6391ALPHA2CODE 
123, en 
137, fr 

LANGUAGE_LOCALIZATION数据

LANGUAGE_ID, LANGUAGE_LOCALIZATION_ID, REFERENCE_NAME 
123,   123,      English 
123,   137,      anglais 

实际的问题是,没有查询当任何语言环境数据(localeCodes为空或空),data.getLocalizations().values()entityManager.find()后返回的仅一个本地化语言名称列表数据(法国的,但我假设这是SQL'随机')。我上午能够得到两个本地化,如果我明确地查询他们(单独或一起),所以我知道数据的那里,并且JPQL查询工作。

当没有针对特定查询进行查询时,我可以做些什么来使它返回两者(全部是,当我有超过2种语言的本地化数据时)本地化?


的实际查询似乎是这样的(部分结果列删除):

SELECT t0.LANGUAGE_ID, t0.LANGUAGE_LOCALIZATION_ID, 
     t1.ISO6391ALPHA2CODE, 
     t0.REFERENCE_NAME 
FROM LANGUAGE_LOCALIZATION t0 
LEFT OUTER JOIN LANGUAGE t1 
ON t0.LANGUAGE_LOCALIZATION_ID = t1.id 
WHERE t0.LANGUAGE_ID = ? [params=?] 

这似乎并没有被限制以任何方式行计数。 (to.LANGUAGE_ID匹配多个行)。尤其是因为,在同一数据集,下面得到两个结果行(部分结果列再次删除):

SELECT t0.LANGUAGE_ID, t0.LANGUAGE_LOCALIZATION_ID, 
     t2.id, t2.ISO6391ALPHA2CODE, 
     t3.id, t3.ISO6391ALPHA2CODE, 
     t0.REFERENCE_NAME 
FROM LANGUAGE_LOCALIZATION t0 
INNER JOIN LANGUAGE t1 
ON t0.LANGUAGE_LOCALIZATION_ID = t1.id 
LEFT OUTER JOIN LANGUAGE t2 
ON t0.LANGUAGE_ID = t2.id 
LEFT OUTER JOIN LANGUAGE t3 
ON t0.LANGUAGE_LOCALIZATION_ID = t3.id 
WHERE (t0.LANGUAGE_ID = ? AND t1.ISO6391ALPHA2CODE IN (?, ?)) [params=?, ?, ?] 

(这带来了为什么它既有t1t3的问题,但是这是后话)

回答

0

我终于想通了,什么是错的 -
我会映射一个一对多映射到键开错列。所需LanguageData的定义改为:

@Entity 
@Table(name = "LANGUAGE") 
public class LanguageData extends PersistedAuditedData<Long> { 

@Id 
@Column 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
private Long id; 

@Column(name = "ISO6391ALPHA2CODE") 
private String iso6391Alpha2Code; 

@OneToMany(fetch = FetchType.LAZY, mappedBy = "languageData") 
@MapKeyColumn(name = "LANGUAGE_LOCALIZATION_ID") 
private Map<Long, LanguageDataLocalization> localizations; 

@OneToMany(fetch = FetchType.LAZY, mappedBy = "localizationLanguage") 
@MapKeyColumn(name = "LANGUAGE_ID") 
private Map<Long, LanguageDataLocalization> languagesLocalized; 

/** 
* Private no-arg constructor for reflection-based construction inside JPA providers. 
*/ 
@SuppressWarnings("unused") 
private LanguageData() { 
    // Fields initialized by JPA. 
} 

// Plus getters for fields 
} 

我的地图概念中应该包含是正确的,但我并没有通过他们应该如何进行键控(关闭的其他思考柱)。

0

您可以启用SQL生成调试,以便我们可以看到SQL代码真的是什么吗?

在冬眠其是这样的: <property name = "hibernate.show_sql" value = "true" />

+1

对不起,可能应该补充一点。编辑问题以包含此信息。 – 2012-07-31 16:05:18