如何使用JPA的MySQL全文搜索

Kev*_*vin 5 full-text-search jpa eclipselink

我想使用JPA 使用MySQL的全文搜索功能,而不必使用本机查询.

我正在使用EclipseLink,它具有支持本机SQL命令的功能:FUNC.但是,帮助示例仅显示这与简单的MySQL函数一起使用.我尽最大努力使其与MATCH&AGAINST合作如下:

@PersistenceContext(name="test")
EntityManager em;

Query query = em.createQuery("SELECT person FROM People person WHERE FUNC('MATCH', person.name) FUNC('AGAINST', :searchTerm)");
...
query.getResultList();
Run Code Online (Sandbox Code Playgroud)

这给出了以下例外:

Caused by: NoViableAltException(32@[()* loopback of 822:9: (m= MULTIPLY right= arithmeticFactor | d= DIVIDE right= arithmeticFactor )*])
    at org.eclipse.persistence.internal.libraries.antlr.runtime.DFA.noViableAlt(DFA.java:159)
    at org.eclipse.persistence.internal.libraries.antlr.runtime.DFA.predict(DFA.java:116)
    at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.arithmeticTerm(JPQLParser.java:4557)
    ... 120 more
Run Code Online (Sandbox Code Playgroud)

我对使用FUNC方法的其他替代方案持开放态度.

我正在使用EJB 3和EclipseLink 2.3.1.

str*_*tle 9

改进了@Markus Barthlen的答案,适用于Hibernate.

创建自定义方言

public class MySQLDialectCustom extends MySQL5Dialect {
  public MySQLDialect() {
    super();
    registerFunction("match", new SQLFunctionTemplate(StandardBasicTypes.DOUBLE,
        "match(?1) against  (?2 in boolean mode)"));
  }
}
Run Code Online (Sandbox Code Playgroud)

并通过设置hibernate.dialect属性进行注册.

用它

在JPQL中:

Query query = entityManager
    .createQuery("select an from Animal an " +
             "where an.type = :animalTypeNo " +
             "and match(an.name, :animalName) > 0", Animal.class)
    .setParameter("animalType", "Mammal")
    .setParameter("animalName", "Tiger");
List<Animal> result = query.getResultList();
return result;
Run Code Online (Sandbox Code Playgroud)

或使用Criteria API:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Animal> criteriaQuery = criteriaBuilder.createQuery(Animal.class);
Root<Animal> root = criteriaQuery.from(Animal.class);

List<Predicate> predicates = new ArrayList<>();

Expression<Double> match = criteriaBuilder.function("match", Double.class, root.get("name"),
criteriaBuilder.parameter(String.class, "animalName"));

predicates.add(criteriaBuilder.equal(root.get("animalType"), "Mammal"));
predicates.add(criteriaBuilder.greaterThan(match, 0.));

criteriaQuery.where(predicates.toArray(new Predicate[]{}));

TypedQuery<Animal> query = entityManager.createQuery(criteriaQuery);
List<Animal> result = query.setParameter("animalName", "Tiger").getResultList();

return result;
Run Code Online (Sandbox Code Playgroud)

此博客文章中的更多详细信息:http://pavelmakhov.com/2016/09/jpa-custom-function


Jam*_*mes 5

FUNC仅适用于普通打印功能,

即MATCH(arg1,arg2)

因为MATCH arg1 AGAINST arg2没有按照正常打印功能的方式打印,所以FUNC不能用来调用它.

EclipseLink ExpressionOperators确实支持这样的打印功能,因此您可以定义自己的ExpressionOperator,但ExpressionOperators目前仅通过EclipseLink Expression查询支持,而不是通过JPQL支持.您可以记录增强功能以​​在JPQL中获得操作员支持.

您还可以使用本机SQL查询.