Timings for a rather complex query:
- web app: 12s
 - pgAdmin4 (ver 5.2): 700ms (more than 12x speedup!)
 
Why this difference? The query resturns only 10 rows with 8 columns.
Using VisualVm to sample my app it shows that my app spends whole query time in socket read so the bottleneck must be on postgres side.
Context:
- create a temporary table 
temp(one columnid integer) - create index on temp table
 - use the temp table in my complex select query
 
SELECT DISTINCT min("baseprop"."first"), max("baseprop"."first"), max("baseprop"."second"), "baseprop"."type", "join1name"."lexeme", count(DISTINCT "baseprop"."first"), , (array_agg(DISTINCT "baseprop"."first"))[1:10], "baseprop"."meaning"
FROM "base"
JOIN "temp" ON "temp"."id" = "base"."id"
JOIN "baseprop" ON "baseprop"."base" = "base"."id"
LEFT OUTER JOIN "join1" ON "baseprop"."join1" = "join1"."id"
LEFT OUTER JOIN "join1name" ON "join1name"."owner" = "join1"."id"
LEFT OUTER JOIN "join2" ON "join2"."id" = "join1"."join2"
WHERE (("baseprop"."meaning" = 'm1'
        AND (("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name11')))), (strip((to_tsvector('en', 'name12')))), (strip((to_tsvector('en', 'name13')))))
              AND "join1"."meaning" = 'm1')
             OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name21')))))
                 AND "join1"."meaning" = 'm1')
             OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name22')))))
                 AND "join1"."meaning" = 'm1')
             OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name23')))))
                 AND "join1"."meaning" = 'm1'))
        AND "join2"."country" = 'en'::country)
       OR ("baseprop"."meaning" = 'm2'
           AND (("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name31')))), (strip((to_tsvector('en', 'name32')))), (strip((to_tsvector('en', 'name33')))), (strip((to_tsvector('en', 'name34')))))
                 AND "join1"."meaning" = 'm2')
                OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name41')))))
                    AND "join1"."meaning" = 'm2')
                OR ("join1name"."lexeme" IN ((strip((to_tsvector('en', 'name51')))))
                    AND "join1"."meaning" = 'm2'))
           AND "join2"."country" = 'en'::country)
       OR ("baseprop"."meaning" = 'm3'
           AND "join1name"."lexeme" IN ((strip((to_tsvector('en', 'name61')))))
           AND "join1"."meaning" = 'm3'
           AND "join2"."country" = 'en'::country)
       OR ("baseprop"."meaning" = 'm4'
           AND "join1name"."lexeme" IN ((strip((to_tsvector('en', 'name71')))))
           AND "join1"."meaning" = 'm4'
           AND "join2"."country" = 'en'::country))
GROUP BY "baseprop"."meaning",
         "baseprop"."type",
         "join1name"."lexeme"
Even without using temp table, I still get 7x speedup diff.
jdbcdriver 'org.postgresql:postgresql:42.2.20'
Postgres 12
EDIT
Seems that the diff is due to PreparedStatement. Issuing a query with raw sql text (embedded params) works as expected.
Related: PreparedStatement very slow, but manual query quick