JPA and JSON operator native query - java

I'm trying to make this query work in JPA:
SELECT * FROM contrat WHERE contrat_json #> '{"nom" :"hever"}';
It works perfectly with postgresql but when I integrate it with JPA, I get the following error:
Parameter with that position [1] did not exist
My code:
#Transactional
#Query(nativeQuery = true,value = "select p from Contrat p where contrat_json #> '{\"nom\":\":nom\"}'")
public List<Contrat> findByNomRestrict(#Param("nom") String nom);
I think it does not recognize #> despite native query, do you have an idea?

Parameter holders are not understood inside literals: '...:nom...' will contain the characters :nom, not the bound values of nom.
For PostgreSQL 9.5 (and later), use:
SELECT * FROM contrat WHERE contrat_json #> jsonb_build_object('nom', :nom)
For 9.4:
SELECT * FROM contrat WHERE contrat_json #> CAST(json_build_object('nom', :nom) AS jsonb)
For 9.3 (and earlier), there is no JSON containment operator (neither the jsonb type).
http://rextester.com/AUHP11519

I had similar problem with my native query.
The jsonb field name is called data, and it's simple
{
"name" : "genderList",
"displayName" : "gender list"
}
I want to find by name with JpaRepository, and here is my Repository
#Repository
public interface LookupListRepository extends JpaRepository<LookupList, UUID>
{
#Query(value = "SELECT * FROM lookup_list WHERE data->>'name' = :name",
nativeQuery = true)
List<LookupList> findByName(#Param("name") String name);
}
You need nativeQuery = true.
With nativeQuery = true, this works as well.
SELECT * FROM lookup_list WHERE jsonb_extract_path_text(data, 'name') = :name
I see your #Transactional annotation, I assume you have the native query on top of application service method. Can you try moving all native query's in repository and use JpaRepository, and use the repository method in your application service?
Here is how my application service uses the repository.
public class LookupListServiceImpl implements LookupListService
{
#Autowired
LookupListRepository lookupListRepository;
#Override
#Transactional
public void changeLookupList(LookupListDto lookupListDto)
{
List<LookupList> lookupLists = lookupListRepository.findByName(lookupListDto.getName());
...
}
}
Reference for JPA repository
http://docs.spring.io/spring-data/jpa/docs/1.3.0.RELEASE/reference/html/jpa.repositories.html

With PostgreSQL and JSON you'll probably run into needing ? or other strange operators, so it's better you just use their function equivalents, instead. You can look them up in the psql console like this \doS+ #>.
Your query is not native, as the parameter says.
select p from Contrat p where...
Will only give you an error when it reaches the database.
Try something like
#Query(nativeQuery = true, value = "select * from Contrat where jsonb_contains(contrat_json, :nom )")
and just bind "{\"nom\":\"" + param + "\"}" as the parameter

Related

dynamic Query in #Query annotation

I have situation in which I have to compose a JPQL query in some method, then pass this query to spring data query method to be used as the query in #Query annotation.
#Query(value = ":DyanamicQuery")
List<PrizeInsuranceConfiguration> filterConfigurPrizeInsurance(String DyanamicQuery);
This is not possible. As it throws compile error. Can you give me an alternat way to achieve this?
#Query(value = ":DyanamicQuery")
List<PrizeInsuranceConfiguration> filterConfigurPrizeInsurance(String DyanamicQuery);
expected to get Query that I made will go and sit at value = ":DyanamicQuery" I also tried giving #Query("#{#entityName}").
You can create a JPQL query as a string, but you cannot pass it as a parameter to the value attribute of the #Query annotation.
You can use below example -
String dyanamicQuery= "SELECT * FROM table_name WHERE condition= :condition";
#Query(value = dyanamicQuery)
List<Entity> findByField(#Param("condition") String condition);
Or you can use below example also -
#Query(value = "SELECT * FROM table_name WHERE condition= :condition")
List filterConfigurPrizeInsuranceByField(#Param("condition") String condition);

Filter JSON column from MySQL table in spring boot

Below is my query to filter the json column in MySQL table ,
public interface MpaCustomizationRepository extends
JpaRepository<MpaCustomization, Serializable> {
#Query(nativeQuery = true, value = "select * from MPA_CUSTOMIZATION where json_contains(domain_based_properties, '{\"id\" : ?1}')")
MpaCustomization findByDomainBaseId(String domainId);
}
above method throws below SQL error,
but if I hard code the variable and run the query like below its works fine,
#Query(nativeQuery = true, value = "select * from MPA_CUSTOMIZATION where json_contains(domain_based_properties, '{\"id\" : 2}')")
MpaCustomization findByDomainBaseId(String domainId);
How to fix this issue?
Use $.id for values when using native query, as SQL accepts like it only.
Other way, you may use :id and bind parameter {\"id\":\"" + <value> + "\"} to the query.
Maybe the following will work.
#Query(nativeQuery = true, value = "select * from MPA_CUSTOMIZATION where json_contains(domain_based_properties, ?1 , '$.id'")
MpaCustomization findByDomainBaseId(String domainId);
Source

JPA: Using criteriabuilder to find entities: Attribute name different from annotation?

I have a mysql database with employee information, each employee has a technical id as primary key. In MySQL to selcet row(s) matching criteria, i can just use to get the following statement (works)
SELECT * FROM database_test.employee WHERE fist_name='First1';
In Java i can also use this as a native statement to get what i want (works):
List<EmployeeEntity2> objects = m_em.createNativeQuery(
"SELECT * database_test.employee WHERE first_name='First1'",
EmployeeEntity2.class).getResultList();
However, i wanted to use the Criteriabuilder to get the same result and later generalize it for multiple columnName=columnEntry selections.
public List<EmployeeEntity2> testNoParameter() {
//Based on https://www.objectdb.com/java/jpa/query/criteria
CriteriaBuilder cb = m_em.getCriteriaBuilder();
CriteriaQuery<EmployeeEntity2> q = cb.createQuery(EmployeeEntity2.class);
Root<EmployeeEntity2> c = q.from(EmployeeEntity2.class);
ParameterExpression<String> p = cb.parameter(String.class);
//Works
//q.select(c).where(cb.equal(c.get("firstName"), p));
//Won't work
q.select(c).where(cb.equal(c.get("first_name"), p));
TypedQuery<EmployeeEntity2> query = m_em.createQuery(q);
query.setParameter(p, "First1");
List<EmployeeEntity2> results = query.getResultList();
return results;
}
Using "fist_name" - the column name annotation from the Entity - will yield the following java.lang.IllegalArgumentException with:
Unable to locate Attribute with the the given name [first_name] on this ManagedType [xx.xxx.database.EmployeeEntity2]
EmployeeEntity2 has "fist_name" annotation:
#Column(name = "first_name", nullable = false)
#Override
public String getFirstName() {
return super.getFirstName();
}
So "first_name" should exist, however (with some debugging) i found out that the attribute expected is for some reason "firstName" instead - which i have not defined/annotated - so where does it come from - and how can i use the column names actually defined in the database (column = "first_name")?
You should use property name of entity (not column name) to use it in criteria builder so instead of
q.select(c).where(cb.equal(c.get("first_name"), p));
use
q.select(c).where(cb.equal(c.get("firstName"), p));
CriteriaBuilder is RDBMS schema agnostic, so you use your model (entities), not schema (table names etc).
In JPA you dont normally use SQL but JPQL. Equivalent of your SQL in JPQL would be something like
"SELECT e FROM EmployeEntity2 e WHERE e.firstName='First1'"
Both CriteriaQuery tree and JPQL string are transformed down to the same query tree later on (can't remember the name), so they both must comply to the very same rules.

Update query not working propertly using namedquery in jpa

I'm trying to update a simple table using jpa. I have written a jpa namedquery for it
#NamedQuery(name="updatedetails",query="update myentity set enddesc=?, startdesc=? Where id=?")
My code is as follows
em.createNamedQuery("updatedetails",myentity.class).serParameter(1, "abcd").serParameter(2,"gjvg").serParameter(3, "gghjj").executeUpdate();
myentity is my class name
It throws me the following error
Encountered "=" at character but expected ["."] While parsing the query
Is there anything wrong with the query
I believe that JPA named queries should use actual names are parameter placeholders, rather than ?, the latter which is used in prepared statements. So something like this should work:
#NamedQuery(name="updatedetails",query="update myentity set enddesc = :enddesc, startdesc = :startdesc Where id = :id")
List<myentity> results = em.createNamedQuery("updatedetails", myentity.class)
.setParameter("enddesc", "abcd")
.setParameter("startdesc", "gjvg")
.setParameter("id", "gghjj")
.getResultList();
As side note, you should probably make your class names begin with uppercase letters, i.e. call it MyEntity, rather than what you currently have.
em.createNamedQuery("updatedetails",myentity.class).serParameter(1, "abcd").serParameter(2,"gjvg").serParameter(3, "gghjj").executeUpdate();
Instead of serParameter use setParameter, should work.
write this code in model class
#NamedQuery(name = "new_ticket_bat.UpdateflagAutres", query = "UPDATE new_ticket_bat t set t.status_AUTRE='0' WHERE t.id= :id")
<br>
write this code in you service class
static void updateflagAutres(String id) {
DataBaseTools dbTools = new DataBaseTools("databaseOv");
try {
Query q=dbTools.em.createNamedQuery("new_ticket_bat.UpdateflagAutres");
q.setParameter("id", id);
q.executeUpdate();
dbTools.em.getTransaction().commit();
dbTools.em.close();
} catch (Exception ex) {
ex.printStackTrace();
Tools.traiterException(Tools.getStackTrace(ex));
}
}

IN-clause in HQL or Java Persistence Query Language

I have the following parametrised JPA, or Hibernate, query:
SELECT entity FROM Entity entity WHERE name IN (?)
I want to pass the parameter as an ArrayList<String>, is this possible? Hibernate current tells me, that
java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String
Is this possible at all?
ANSWER: Collections as parameters only work with named parameters like ":name", not with JDBC style parameters like "?".
Are you using Hibernate's Query object, or JPA? For JPA, it should work fine:
String jpql = "from A where name in (:names)";
Query q = em.createQuery(jpql);
q.setParameter("names", l);
For Hibernate's, you'll need to use the setParameterList:
String hql = "from A where name in (:names)";
Query q = s.createQuery(hql);
q.setParameterList("names", l);
in HQL you can use query parameter and set Collection with setParameterList method.
Query q = session.createQuery("SELECT entity FROM Entity entity WHERE name IN (:names)");
q.setParameterList("names", names);
Leaving out the parenthesis and simply calling 'setParameter' now works with at least Hibernate.
String jpql = "from A where name in :names";
Query q = em.createQuery(jpql);
q.setParameter("names", l);
Using pure JPA with Hibernate 5.0.2.Final as the actual provider the following seems to work with positional parameters as well:
Entity.java:
#Entity
#NamedQueries({
#NamedQuery(name = "byAttributes", query = "select e from Entity e where e.attribute in (?1)") })
public class Entity {
#Column(name = "attribute")
private String attribute;
}
Dao.java:
public class Dao {
public List<Entity> findByAttributes(Set<String> attributes) {
Query query = em.createNamedQuery("byAttributes");
query.setParameter(1, attributes);
List<Entity> entities = query.getResultList();
return entities;
}
}
query.setParameterList("name", new String[] { "Ron", "Som", "Roxi"}); fixed my issue

Categories

Resources