2

CREATE TABLE IF NOT EXISTS posts(
    postid SERIAL NOT NULL,
    owner SERIAL NOT NULL,
    title VARCHAR(100) UNIQUE NOT NULL,
    message VARCHAR(500) NOT NULL,
    continent VARCHAR(100) NOT NULL,
    country VARCHAR(100) NOT NULL,
    state VARCHAR(100) NOT NULL,
    languages VARCHAR(100)[] NOT NULL,
    properties varchar(100) ARRAY NOT NULL,
    PRIMARY KEY (postid),
    FOREIGN KEY (owner) REFERENCES users(userid) ON DELETE CASCADE
);
final Query query = em.createNativeQuery("SELECT postid FROM posts WHERE :properties <@ properties");
query.setParameter("properties", propAux);

I'm migrating my project to hibernate (I'm using the version 1.0.0.Final of javax.persistence.Query), and I can't seem to run that query. It says that <@ operator doesn't work with types bytea and suggests to cast it. I tried casting it to text[], replacing :properties <@ properties with cast(:properties as text[]) <@ cast(properities as text[]) but didn't work either.

Any suggestions?

PS: propAux is an array of Strings.

vanderkute
  • 21
  • 4
  • What type is the column "properties"? – jjanes Jun 03 '21 at 23:47
  • The type is varchar(100)[] – vanderkute Jun 04 '21 at 00:48
  • Surely the error message changed when you added the cast? Please copy and paste the exact error message – jjanes Jun 04 '21 at 13:36
  • Caused by: org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to text[] Position: 44 – vanderkute Jun 04 '21 at 14:47
  • Maybe one of the answer's [here](https://stackoverflow.com/questions/40020972/bind-array-param-to-native-query) would help? Options discussed there are passing in a string like `"{'a','b','c'}"` and casting to array, or using ```setParameter("properties", new TypedParameterValue(StringArrayType.INSTANCE, propAux)) ``` You could use something like `select pg_typeof(:properties)` to see what's bound in. – roby Jun 06 '21 at 01:08

1 Answers1

0

Assuming that you have the following setup:

create table TST_POSTS
(
   postid int,
   properties varchar(200)[],
   
   primary key (postid)
);

insert into TST_POSTS
values (1, '{"aaa", "bbb"}'), (2, '{"aaa", "ccc"}'), (4, '{"ddd", "ccc"}');

You can write the following query:

import org.hibernate.jpa.TypedParameterValue;
import com.vladmihalcea.hibernate.type.array.StringArrayType;

// ...

List<Integer> results = entityManager
   .createNativeQuery("select postid from TST_POSTS where :prop <@ cast(properties as text[])")
   .setParameter("prop", new TypedParameterValue(StringArrayType.INSTANCE, new String[] {"ccc"}))
   .getResultList();

and you will get the output:

2
4

This approach requires to have hibernate-types as a dependency.

P.S. I tested it with hibernate-types-52 (version 2.10.1) and hibernate 5.4.29.Final. See also this article.

EDIT

You can use the following query for hibernate 5.1.0.Final:

import org.hibernate.Query;
import com.vladmihalcea.hibernate.type.array.StringArrayType;

// ...

Query query = entityManager
   .createNativeQuery("select postid from TEST_SCHEMA.TST_POSTS where :prop <@ cast(properties as text[])")
   .unwrap(Query.class)
   .setParameter("prop", new String[] {"ccc"}, StringArrayType.INSTANCE);

@SuppressWarnings("unchecked")
List<Integer> result = query.list();

and you should use the following dependency:

<dependency>
   <groupId>com.vladmihalcea</groupId>
   <artifactId>hibernate-types-5</artifactId>
   <version>2.11.1</version>
</dependency>

instead of hibernate-types-52.

SternK
  • 11,649
  • 22
  • 32
  • 46
  • Yes, I have a similar setup. I'll edit the post and add it so you can see. I did what you suggested here. But still for some reason it reads my varchar(100)[] from the db as bytea and I get this error: Caused by: org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to text[] Position: 44 The problem is obviously coming from the cast(properties as text[]). I also don't have that version of hibernate. I have version 5.1.0.Final. – vanderkute Jun 04 '21 at 14:48
  • 1. Why you use 5.1.0.Final instead of the latest version from 5.4 branch? 2. What hibernate dialect do you use? – SternK Jun 04 '21 at 15:00
  • Apparently I tried doing away with cast() and still got the same error. So maybe the error does come from casting it in the TypedParameterValue function? – vanderkute Jun 04 '21 at 15:04
  • I use 5.1.0.Final because other things depend on it and can't change it because they all break. – vanderkute Jun 04 '21 at 15:05
  • Even if I do away with TypedParameterValue() it still gives me the same error. I honestly don't know what to do anymore haha – vanderkute Jun 04 '21 at 15:09
  • The hibernate dialect I am using is: "org.hibernate.dialect.PostgreSQL92Dialect" – vanderkute Jun 04 '21 at 15:13
  • MY BAD Apparently I have the version 5.1.4.FINAL I forgot I had changed it. I'm sorry man – vanderkute Jun 04 '21 at 18:26
  • Basically for version 5.1.4.FINAL I can't use the fucntion setParameter(String, String[], StringArrayType.INSTANCE) (It doesn't exist) – vanderkute Jun 04 '21 at 18:32
  • I also set the function unwrap(Query.class) but it did nothing so far. – vanderkute Jun 04 '21 at 18:33
  • I'm sorry I should have double checked my version – vanderkute Jun 04 '21 at 18:35
  • It is not important, the above solution for `5.1.0.Final` should work for the `5.1.4.Final` version too. – SternK Jun 04 '21 at 19:02
  • Mmhh doesn't work for me. It says"the method setParameter(Str, Clanedar, TemporalType) in the query is not applicable for the argumetns (Str, Str[],..) – vanderkute Jun 04 '21 at 19:24
  • my org.hibernate.jpa.version is 1.0.0.Final My org.hibernate.version is 5.1.4.Final – vanderkute Jun 04 '21 at 19:36
  • org.hibernate.javax.persistence hibernate-jpa-2.1-api ${org.hibernate.jpa.version} I notice that I'm using javax.persistence for the type Query. – vanderkute Jun 04 '21 at 19:39
  • yes, that's definitely the issue here. I'm using javax.persistence.Query instead of org.hibernate.Query; I can't replace it because I've worked with javax.persistence all the time. Could there be a solution to this using javax.persistence.Query? – vanderkute Jun 04 '21 at 19:44