2017-10-09 175 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