JPA2标准不依赖于数据库的重音不敏感

时间:2014-07-14 19:00:24

标签: java sql jpa jpa-2.0

我在JPA2中使用本机查询进行此查询,以搜索独立于案例或重音的parcial文本(基于http://www.guj.com.br/java/212706-accent-insensitive-hibernate):

public List<Hipotesis> findHipotesisByText(String srchtext) {
    EntityManager em = getEntityManager();

    String textNormalized =
        Normalizer.normalize(srchtext, Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "").toUpperCase();

    Query query =
        em.createNativeQuery(
            "select * from HIPOTESIS where ( UPPER(TRANSLATE( TEXTFIELD,'ÀÁÂÃáàâãÉÈÊéèêÍíÓÒÔÕóòôõÚÜúü','AAAAaaaaEEEeeeIiOOOOooooUUuu' ) ) like '%" + textNormalized + "%'",
            Hipotesis.class);

    @SuppressWarnings("unchecked")
    List<Hipotesis> results = query.getResultList();
    return results;

}

将搜索文本规范化为条带重音并转换为大写。 本机查询使用TRANSLATE将重音转换为纯文本,UPPER将结果转换为大写。

因此,搜索文本eMeRgÊ将被标准化为EMERGE,并将匹配数据库中的任何出现,如emergencia,emergência,Emergência。

虽然SQL99指定了TRANSLATE,但它不支持或实现与标准完全相同。

问题:有没有办法在不使用TRANSLATE的情况下实现此查询?或者不使用原生查询?

1 个答案:

答案 0 :(得分:2)

在我个人看来,最优雅的解决方案是实际复制数据并将其转换为标准化形式。您在查询中使用LIKE条件,这基本上排除了任何正常(缺少全文)索引机制。这意味着TRANSLATE查询很可能效率低下且难以优化。

使用JPA,您可以利用实体​​生命周期事件以相当方便的方式管理规范化表单:

@Entity
public class Whatever implements Serializable {
    private static final long serialVersionUID = 0L;

    private String string;
    private String normalizedString;

    // getters and setters

    @PreUpdate
    @PrePersist
    protected void normalize() {
        normalizedString = yourNormalizationMethod(string);
    }
}

我认为这是解决此类问题的最干净,最优雅,最与数据库无关的方法。