2017-10-09 167 views
1

在我当前的项目中,我们将折射器对数据库实体的nls支持。在我们以前的版本中,我们使用会话语言,但不幸的是,这种行为并不完全稳定。所以我们将更改代码,以便语言信息存储在查询中。 我很想有一个中央实例来处理这种语言行为,而不是改变每个查询,在每个实体遍布整个项目。Eclipselink:使用定制器添加子句子

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 = :localeNamedQuery和更改所有调用,在这个NamedQuery引用。

更有利的方法是让Customizer添加区域设置参数。 ATM我有这样的:

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

如果你不介意使用特定供应商的解决方案,你可以将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条件,以绑定您在实体管理器上设置的值。

+0

我也想过这个。问题是,该语言可能会在EntityManager的生命周期内发生变化。 Eclipselink的状态[这里](http://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_additionalcriteria.htm):“不要更改实体管理器生命周期的属性。” –

+0

嗯,我也读过。但我不知道你在使用什么环境;如果您处于JEE环境并使用事务范围的实体管理器,则实体管理器的生命周期是当前方法的范围或启动事务的方法的范围。如果你的配置在这个范围内发生了变化,那么我认为这不会对你有所帮助。 – ujulu