Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA Criteria Api select objects where column is null

I have a table "word" in PostgreSQL DB:

CREATE TABLE word
(
   word_id bigserial NOT NULL,
   word character varying(15) NOT NULL,
   counter integer NOT NULL,
   base_letters character varying(15),
   CONSTRAINT word_pk PRIMARY KEY (word_id )
)

And I have a DAO method which has to find all words in table where the column 'base_letters'. I use Spring in general. My method:

    public List<Word> getAllWordsWithoutBaseLetters() {
        CriteriaQuery<Word> c = cb.createQuery(Word.class);
        Root<Word> words = c.from(Word.class); 
        c.select(words).where(cb.isNull(words.get("base_letters")));
        TypedQuery<Word> q = entityManager.createQuery(c);
        List<Word> allWordsWithoutBaseLetters = q.getResultList();
        return allWordsWithoutBaseLetters;
    }

Unfortunately i am getting an error which confuses me:

ERROR [org.springframework.scheduling.support.MethodInvokingRunnable] - Invocation of method 'setBaseLettersToAllWordsWithoutThem' on target class [class $Proxy48] failed
java.lang.IllegalArgumentException: Unable to resolve attribute [base_letters] against path
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.unknownAttribute(AbstractPathImpl.java:118)
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:223)
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:194)
    at pl.net.grodek.snd.dao.WordDaoImpl.getAllWordsWithoutBaseLetters(WordDaoImpl.java:95)
    at pl.net.grodek.snd.service.WordServiceImpl.setBaseLettersToAllWordsWithoutThem(WordServiceImpl.java:175)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy48.setBaseLettersToAllWordsWithoutThem(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
    at org.springframework.scheduling.support.MethodInvokingRunnable.run(MethodInvokingRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Please explain me what is wrong.

like image 583
Mariusz Grodek Avatar asked Aug 01 '12 20:08

Mariusz Grodek


1 Answers

You need to use the name of the java attribute instead of the name of the table column.

This applies to JPQL queries, as opposed to native queries (which are SQL-based).

Assuming the attribute is called baseLetters, you can replace with :

c.select(words).where(cb.isNull(words.get("baseLetters")));
like image 101
kgautron Avatar answered Nov 02 '22 23:11

kgautron