Postgresql jsonb column with spring jpa nativequery issue - postgresql

I have a native query defined in a spring JpaRepositroy as:
#Query(value="Select * from Employee WHERE....", nativeQuery=true)
List<Employee> getEmployees(....)
In entity, I have a jsonb field defined as:
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
....
#Type(type = "jsonb")
#Column(name = "properties", columnDefinition = "jsonb")
private ObjectNode properties;
This setup works perfect, and it fetches the records for me correctly.
But if I try to fetch only some specific columns by changing query as:
#Query(value="Select emp_name, properties from Employee WHERE....", nativeQuery=true)
List<Object[]> getEmployees(....)
This gives me error as:
Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111
And I get this error only if properties field is in SELECT clause, else this too works fine.
What is the reason? And how to get it working with properties field?

Related

How to JPA Query for Postgresql #Type list-array?

I have column in a database in which data are stored in this way {type1,type2,...}. I want to get elements from CARS table which are in Set carTypes.
#Type(type = "list-array")
#Column(name = "TYPES")
private final List<String> types;
Not working:
#Query("SELECT * FROM cars c WHERE (:carTypes) IN (c.types)")
List<Object[]> findCars(#Nullable #Param("carTypes") Set<String> carTypes);
Error:
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: bytea = character varying[]
I don't know what the Spring Data abstraction for this (or if there is any), but with plain Hibernate you can do something like this:
BasicType type = (BasicType) session.getFactory()
.getMappingMetamodel()
.getEntityDescriptor(Car.class)
.getPropertyType("types");
List<Car> list = session.createQuery(
"SELECT * FROM cars c WHERE (:carTypes) IN (c.types)",
Car.class
)
.setParameter("carTypes", carTypes, type)
.getResultList();

Querying by value in JSONB field in h2/postgresql

I have following json field in entity:
{"uuid", "uuid2"}
and I want to use #Query to find an entity which contains given uuid in this field. I have found a solution for postgresql (which we are using), but when I try to test it using h2 I get Function JSONB_EXISTS not found exception.
Is it possible to make it work with both postgresql and h2 using same query?
How I am creating a query (this works fine for postgresql, but not for h2):
#Query(
nativeQuery = true,
value = "SELECT * FROM patient_person WHERE jsonb_exists(patient_reference_ids, :patientReferenceId)"
)
fun findByPatientReferenceId(#Param("patientReferenceId") patientReferenceId: String): PatientPersonEntity?
How is field defined in entity:
#Type(type = "jsonb")
#Column(columnDefinition = "jsonb")
var patientReferenceIds: emptyList()
Error during test run
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Function "JSONB_EXISTS" not found; SQL statement:
SELECT * FROM patient_person WHERE jsonb_exists(patient_reference_ids, ?) [90022-200]

spring boot JPA returns null object when it finds a null attribute eg date is null

I wanted to load an object from the database that contains more
attributes, one of which is null (e.g : date), using spring boot JPA
that returns a null object because it found the date is null despite
the object exists in the database. Please who can who can tell me how I solve this problem
#Entity #IdClass(Exemple.class) #Table(name= "table") public class
Exemple implements Serializable{
#Id #Column(columnDefinition = "id_activite") private Integer idActivite;
//the Problem is here
#Column(columnDefinition = "date_debut_prevue") #Nullale private Calendar dateDebutPrevue;
//Other attribute and Id
#Id ...
// Getters && setters
}
//Query Repository
#Query("SELECT ar FROM table ar where ar.idActivity = ?1 ")
List<Activitie> findAllPositionByIdActivitie(Integer idActivitie);
Your query is a native query and not a JPQL query.
The query must use the Entity name in the FROM clause not the table name.
#Query("SELECT ar FROM Exemple ar where ar.idActivity = ?1 ")
List<Activitie> findAllPositionByIdActivitie(Integer idActivitie);

Hibernate OGM with MongoDB could not resolve property

This HQL query give me error:
String q4 = "SELECT i, COUNT(ie) FROM CorsoStudi cs \n"
+ "\t JOIN cs.inserogati ie JOIN ie.insegn i \n"
+ "\t WHERE cs.nome = 'Laurea in Informatica' \n"
+ "\t GROUP BY i";
The error is:
Exception in thread "main" java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: insegn. of: component[_id,annierogazione,annoaccademico,crediti,discriminante,discriminantemodulo,hamoduli,id_facolta,insegn,inserogato_padre,modulo,nomemodulo,nomeunita,programma]
This is InsErogato:
#Embeddable
public class InsErogato {
private Integer _id;
private String annoaccademico;
#Embedded
private Insegn insegn;
#Embedded
private Discriminante discriminante;
private Integer modulo;
private String discriminantemodulo;
private String nomemodulo;
private Double crediti;
private String programma;
private Integer id_facolta;
private String hamoduli;
#Embedded
private InsErogatoPadre inserogato_padre;
private String nomeunita;
private Integer annierogazione;
// constructors, getters and setters and toString
}
and this is Insegn:
#Embeddable
public class Insegn {
private Integer _id;
private String nomeins;
private String codiceins;
// constructors, getters and setters and toString
}
Main:
// begin transaction
entityManager.getTransaction().begin();
List<Object[]> insegn = entityManager
.createQuery(q4, Object[].class)
.getResultList();
for(Object[] i : insegn) {
Insegn ins = (Insegn)i[0];
Long count = (Long)i[1];
System.out.println("nomeins: " + ins.getNomeins() + ", numero inserogati: " + count);
}
// commit transaction
entityManager.getTransaction().commit();
The MongoDB structure:
https://i.stack.imgur.com/qFusC.jpg
https://i.stack.imgur.com/k04HK.png
https://i.stack.imgur.com/H8nhS.png
https://i.stack.imgur.com/eYl2M.png
I tried to change the query but Hibernate doesn't find "insegn" (and also "discriminante") property in "inserogato", but he can find other simple attributes from it (like "annoaccademico" etc.).
The same query works on Hibernate ORM with PostgreSQL.
Maybe I have to add something in the annotations, or change the mongoDB structure (?).
I'm using Hibernate OGM 5.3.1.Final and MongoDB 3.6.3 JDBC Driver.
The same query works on Hibernate ORM with PostgreSQL
But PostgreSQL is a SQL database, MongoDB is a NoSQL database. Hibernate OGM is a means to add Hibernate ORM to NoSQL databases. The '(H)SQL' for OGM is limited (see below).
You don't say what your application is deployed on. I use WildFly 12.0.0.Final. I've had OGM with MongoDB working on version 11 & 12.
entityManager.getTransaction().begin();
I use the (WildFly) container to handle transactions. Annotate my EJB.
#TransactionManagement(TransactionManagementType.CONTAINER)
I don't believe you can use (H)SQL per se with Hiberate OGM but:
Use JPQL - only for simple queries for now
Use the NoSQL native query mapping the result as managed entities
Use Hibernate Search queries - primarily full-text queries
It says in the documentation:
In particular and of notice, what is not supported is:
cross entity joins
JPQL functions in particular aggregation functions like count
JPQL update and delete queries
One of my queries:
Query query = mongoDBEntityManager.createQuery("FROM FoodsCosmeticsMedicines f WHERE f.ean = :ean")
.setParameter("ean", ean);
The entity (the #Expose are for the JSON)
#Entity(name = "FoodsCosmeticsMedicines")
#Indexed
#Table(name = "foodsCosmeticsMedicines")
public class FoodsCosmeticsMedicines implements Serializable {
// Arrays of Objects
#Expose(deserialize = true, serialize = true)
#Embedded
ProductCharacteristics productCharacteristics;
#Expose(deserialize = true, serialize = true)
#Embedded
CalcNutrition calcNutrition;
#Expose(deserialize = true, serialize = true)
#Embedded
Nutrients nutrients;
#Expose(deserialize = true, serialize = true)
#Embedded
Enumbers enumbers;
#Expose(deserialize = true, serialize = true)
#Embedded
ChemicalsMineralsVitamins chemicalsMineralsVitamins;
#Expose(deserialize = true, serialize = true)
#Embedded
Lifestyle lifestyle;
.....
}
Why are you using JOIN?
With MySQL I use Hibernate as my ORM I would use annotations to map relationships with entities such as:
#OneToOne(cascade = CascadeType.ALL, mappedBy = "product", fetch = FetchType.LAZY)
private UriEntity uri;
entityManager.getTransaction().commit();
This is irrelevant as all you've done is read. Maybe you excluded the persist?
I'm sure you've read the documentation. I found all the answers to the problems I encountered here:
Hibernate OGM 5.3.1.Final: Reference Guide
Currently, queries with group by are not supported. You will need to run a native MongoDB query for this particular use case. See the reference documentation for more details about it.
I think the join on an embedded entity instead of a collection is confusing the parser even if it's a valid query. You should see a clearer exception with the following one (equivalent to the one you are trying):
SELECT ie.i, COUNT(ie)
FROM CorsoStudi cs
JOIN cs.inserogati ie
WHERE cs.nome = 'Laurea in Informatica'
GROUP BY ie.i;
It should throw:
java.lang.UnsupportedOperationException: The GROUP BY clause is not supported
Aggregate functions are not supported as well.

Query value of JoinColumn with JPQL

I have two JPA entities
public class Job {
#ManyToOne
#JoinColumn(name = "service")
public Service service;
#Column(name = "queue_time")
public Long queueTime;
#Column(name = "run_time")
public Long runTime;
}
public class Service {
#Id
#Column(name = "id")
public Long id;
#Column(name = "name")
public String name;
#Column(name = "host")
public String host;
}
Now I want to do some aggregation queries with JPQL:
SELECT job.service.id, AVG(job.queueTime), AVG(job.runTime) FROM Job job GROUP BY job.service.id
The resulting SQL query (I'm using a MySQL database) looks like this:
SELECT t0.id, AVG(t1.queueTime), AVG(t1.runTime) FROM Service t0, Job t1 WHERE (t0.service = t1.id) GROUP BY t0.id
As you can see, JPA translates my JPQL query to a SQL query with a join. This however slows down the query dramatically. The following SQL query executes ~6 time faster and returns the exact same result set:
SELECT t1.service, AVG(t1.queueTime), AVG(t1.runTime) FROM Job t1 GROUP BY t1.service
If I change the JPQL query to
SELECT job.service, AVG(job.queueTime), AVG(job.runTime) FROM Job job GROUP BY job.service
the resulting SQL query looks like this:
SELECT t0.id, t0.name, t0.host AVG(t1.queueTime), AVG(t1.runTime) FROM Service t0, Job t1 WHERE (t0.service = t1.id) GROUP BY t0.id, t0.name, t0.host
Is there a way to write the JPQL which only queries the job table without making a join to the service table?
This question solved the issue for me: How can I retrieve the foreign key from a JPA ManyToOne mapping without hitting the target table?
I took the second solution (b) Use read-only fields for the FKs)