我在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的情况下实现此查询?或者不使用原生查询?
答案 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);
}
}
我认为这是解决此类问题的最干净,最优雅,最与数据库无关的方法。