在我目前的项目中,我们将对数据库实体的nls支持进行折射。在我们之前的版本中,我们使用了会话语言,但不幸的是,这种行为并不完全稳定。因此我们将更改代码,以便将语言信息存储在查询中。 我希望有一个中心实例来处理这种语言行为,而不是在整个项目中的每个实体中更改每个查询。
E.g。我有这个实体:
@NamedQueries({
@NamedQuery(name = NLSBackendEntity.findAll,
query = "select n from NLSBackendEntity n"),
@NamedQuery(name = NLSBackendEntity.getById,
query = "select n from NLSBackendEntity n where n.nlsBackendKey.key = :key") })
@Entity
@Table(name = "backend_key_al")
public class NLSBackendEntity implements Serializable
{
private static final long serialVersionUID = 1L;
public static final String findAll = "NLSBackend.findAll";
public static final String getById = "NLSBackend.getById";
@EmbeddedId
private NLSBackendKey nlsBackendKey;
/**
* The text in the language.
*/
@Lob
@Column(name = "TEXT")
private String text;
NLSBackendEntity()
{
// no arg constructor needed for JPA
}
public String getKey()
{
return nlsBackendKey.key;
}
public String getLanguage()
{
return nlsBackendKey.language;
}
public String getText()
{
return text;
}
@Embeddable
public static class NLSBackendKey implements Serializable
{
private static final long serialVersionUID = 1L;
/**
* the NLS-key.
*/
@Column(name = "KEY")
private String key;
/**
* The language of this entry.
*/
@Column(name = "LOCALE")
private String language;
}
}
现在有一种可能性是将n.nlsBackenKey.language = :locale
添加到每个NamedQuery
并更改每个调用,其中引用了此NamedQuery
。
更有利的方法是,Customizer
添加区域设置参数。我有这个:
public class QueryLanguageCustomizer implements DescriptorCustomizer
{
@Override
public void customize(ClassDescriptor descriptor) throws Exception
{
ExpressionBuilder eb = new ExpressionBuilder(descriptor.getJavaClass());
Expression languageExp = eb.getField("LOCALE").equal(eb.getParameter("locale"));
descriptor.getQueryManager().setAdditionalJoinExpression(languageExp);
}
}
我将其添加到NLSBackendEntity
:@Customizer(QueryLanguageCustomizer.class)
但是现在,我无法设置此参数。再一次,我最喜欢的方式是使用SessionEventAdapter
:
public class LanguageSessionEventListener extends SessionEventAdapter {
/** Log for logging. */
private static final Log LOG = LogFactory
.getLog(LanguageSessionEventListener.class);
@Override
public void preExecuteQuery(SessionEvent event) {
LOG.debug("preExecuteQuery called for session= "
+ event.getSession().getName());
event.getQuery().getTranslationRow().put("LOCALE", getLocale());
super.preExecuteQuery(event);
}
private String getLocale() {
// uninteresting for this example
}
}
不幸的是,无论我尝试什么,我都无法设置此参数。 getTransaltionRow()
返回null
,我尝试过的所有其他可能性都失败了。
是否有可能在preExecuteQuery
块内设置此参数?
我正在使用Eclipselink 2.5,非常感谢任何帮助
答案 0 :(得分:0)
如果您不介意使用特定于供应商的解决方案,则可以使用EclipseLink @AdditionalCriteria
注释。您可以按如下方式使用它:
创建一个抽象映射类并从中派生所有实体:
@MappedSuperclass
@AdditionalCriteria("this.language = :lang")
public class AbstractEntity {
private String language;
// getters + setters
}
让您的实体将其子类化:
public class NLSBackendEntity extends AbstractEntity implements Serializable {
// ...
}
在实体管理器或实体管理器工厂中设置language
属性的值:
entityManager.setProperty("language", "de");
。 EclipseLink应将language = ?
附加到查询的where条件,以绑定您在实体管理器上设置的值。
答案 1 :(得分:0)
您可以使用ThreadLocal<String> threadProps = new ThreadLocal<String>();
,将其设置为数据或恢复工厂类并在代码中使用。
如果您未在函数中创建任何新的其他线程,则上述解决方案将起作用。
您可以使用threadProps.get();