Оператор SQL "LIKE" в API Hibernate Criteria

Я хочу реализовать какой-то универсальный фильтр с Hibernate Criteria, Должно работать как LIKE оператор из SQL:

SELECT * FROM table WHERE table.ANYCOLOUMNHERE LIKE '%'||anyvaluehere||'%'

я имею Map<String, String> где ключ - это имя столбца, а значение - его значение.

Я попробовал что-то вроде этого:

for (Entry<String, String> filter : filters.entrySet()) {
    crit.add(Restrictions.ilike(filter.getKey(), filter.getValue(), MatchMode.ANYWHERE));
}

Но когда тип поля не String, это вызывает java.lang.ClassCastException:

[com.nsn.util.LoggerUtilerror] (http-localhost-127.0.0.1-8080-1) Error while getting alarms: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
    at org.hibernate.type.descriptor.java.LongTypeDescriptor.unwrap(LongTypeDescriptor.java:36) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.type.descriptor.sql.BigIntTypeDescriptor$1.doBind(BigIntTypeDescriptor.java:57) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:92) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:305) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:300) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.bindPositionalParameters(Loader.java:1891) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.bindParameterValues(Loader.java:1862) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1737) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.doQuery(Loader.java:828) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2447) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2433) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2263) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.Loader.list(Loader.java:2258) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:122) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1535) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at org.hibernate.internal.CriteriaImpl.uniqueResult(CriteriaImpl.java:396) [hibernate-core-4.1.1.Final.jar:4.1.1.Final]
    at com.nsn.entities_proccess.AlarmDAOImpl.getAlarms(AlarmDAOImpl.java:93) [classes:]
    at com.nsn.boundary_process.LazyAlarmDataModel.load(LazyAlarmDataModel.java:50) [classes:]
    at org.primefaces.component.datatable.DataTable.loadLazyData(DataTable.java:677) [primefaces-3.3.1.jar:]
    at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:92) [primefaces-3.3.1.jar:]
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1786) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:518) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at javax.faces.component.UIData.visitTree(UIData.java:1411) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at javax.faces.component.UIForm.visitTree(UIForm.java:371) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1623) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:376) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:297) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:981) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:391) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) [jsf-impl-2.1.7-jbossorg-2.jar:]
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
    at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
    at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
    at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_05]


Есть ли способ решить эту проблему?

5 ответов

Решение

Я рекомендую использовать Query object вместо Criteria object, в этом случае.

Я не могу вспомнить, передает ли Criteria то, что он не понимает, напрямую в базу данных, как это сделает объект Query. По сути, это означает, что если вы используете функцию, специфичную для базы данных, которую не понимает парсер Hibernate, она передаст ее "как есть" в базу данных.

Пример:

Query queryObject = session.createQuery("from ClassName where VARIABLENAME like '%'||anyvaluehere||'%' order by VARIABLENAME");
List<YourClass> resultList= queryObject.list();

Подробнее смотрите здесь

Ты можешь использовать like() критерии ограничения как это:

session = sessionFactory.openSession();
Criteria query = session.createCriteria(Pojo.class);
query.add(Restrictions.like("anycolumn", "anyvalue", MatchMode.START));

Это даст вам список строк, которые начинаются с " anyvalue ".

Вы также можете использовать DetachedCriteria, когда сеанс гибернации отсутствует.

DetachedCriteria criteria = DetachedCriteria.forClass(Pojo.class);
criteria.add(Restrictions.like("column", value, MatchMode.ANYWHERE));

Это будет соответствовать значению в любом месте строки столбца. Вы можете использовать разные типы режимов.

Справочная страница: https://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/criterion/MatchMode.html

DetachedCriteria:

- Отдельный критерий является очень хорошей альтернативой, когда сеанс гибернации отсутствует.

Использование DetachedCriteria в точности совпадает с критерием, за исключением того, что вы можете выполнить первоначальное создание и настройку запроса, не имея доступа к сеансу. Когда приходит время выполнить ваш запрос, вы должны преобразовать его в исполняемый запрос с getExecutableCriteria(session),

Это полезно, если вы создаете сложные запросы, возможно, с помощью многоэтапного процесса, потому что вам не нужен доступ к сеансу везде. Вам нужен сеанс только на последнем этапе, когда вы запускаете запрос.

Под капотом DetachedCriteria используется CriteriaImpl, который является тем же классом, который вы получите, если позвоните session.createCriteria(),

Используйте enum MatchMode, чтобы помочь вам с этим:

Criterion c1 = Restrictions.like("AttributeName", "AttributeValue", MatchMode.END);

Не используйте специальные символы, такие как * Referencce Read This Like

когда тип поля не является String, он может вызывать java.lang.ClassCastException

это потому, что он работает только со строковыми /varchar полями / столбцами.

Другие вопросы по тегам