I want to write a recursive query in SQL Server. So I am using CTE. Query is working properly in SSMS but when I am trying to use the same CTE in JPA as native SQL it gives an error:
Invalid name column Id.
The entity (which I am using in CTE to fetch data recursively) has #Id #Column(name="pk_id") private int Id field.
I also followed this SOQ : cte sql to simple subset query for JPA
But still getting error as invalid name column Id.
I have never used CTE before. How can this be fixed?
You can write the SQL query in JPA Repositories since the #Query annotation takes native query as well. For that, you need to specify the SQL query in the value parameter and nativeQuery is true as follow.
You can write CTE queries as well.
public interface ISomeRepository extends JpaRepository<Entity, Long> {
#Query(value = "SQL QUERY NEED TO BE WRITTEN HERE", nativeQuery = true)
List<Long> getEntityIds();
}
Related
I am using JPA with spring Boot, and Postgres. I am trying to run a native query using a repository that extends org.springframework.data.repository.CrudRepository. The query looks like this:
public interface MyRepository extends CrudRepository<MyObject, String> {
...
#Query(value = "SELECT * FROM objects WHERE metadata #>
jsonb_build_object('tenant', :tenant , 'objectType', :objectType )", nativeQuery = true)
List<MyObject> findAllBy(#Param("tenant") String tenant, #Param("objectType") String objectType);
...
}
When I run the query I get the error:
org.postgresql.util.PSQLException: ERROR: could not determine data
type of parameter $1
I went over many similar cases but can't get this query to work in this or similar variations.
Table create statement:
create table objects
(
key varchar(256),
tenant varchar(256),
metadata jsonb,
data jsonb
);
Any ideas what I'm doing wrong?
Additional variation I have tried (this time with a pageable object):
#Query(value = "SELECT * FROM objects WHERE metadata #> jsonb_build_object(\\'tenant\\', ?1 , \\'objectType\\', ?2) ORDER BY ?#{#pageable}",
countQuery = "SELECT count(*) FROM objects WHERE metadata->>\\'tenant\\' = ?1 and metadata->>\\'objectType\\' = ?2",
nativeQuery = true)
Page<OSObject> findAllBy(String tenant, String objectType, Pageable pageable);
This results in:
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
I'm still in the dark...
I think this is because jsonb_build_object accepts variadic arguments. You need a typecast to tell Postgresql the data type of the keys and values provided as variables (text or ints or whatever else), otherwise it doesn't know what data type to use inside the json.
jsonb_build_object('key', $1::text)
I don't know anything about Java and Spring, but I imagine it tries to use a prepared statement with dollar variables under the hood. Try to cast your variables with ::text.
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);
or at least the conditions part
#Query(value = "SELECT c FROM PrizeInsuranceConfiguration c WHERE :DyanamicConditions")
List<PrizeInsuranceConfiguration> filterConfigurPrizeInsurance(String DyanamicConditions);
Do, you can do that. There are two reasons why not:
sql injection (spring data work with prepared statements);
(result of first reasone) spring data create query tree and bind all params
But if you need dynamic query you can use Specifications, Query by Example or Querydsl.
I would like to perform a database bulk update using Spring's HibernateTemplate (Hibernate 5.1).
HibernateTemplate offers the following interface: public int bulkUpdate(String,Object...).
My query is UPDATE entity item SET item.attribute.id = ? WHERE item.id in (?.....?).
I had a lot of troubles and want to ask what is the proper way to use HibernateTemplate
The above query results in the deprecation warning [DEPRECATION] Encountered positional parameter near line 1, column 172 in HQ
Replacing the above query with JPA-style parameters (UPDATE entity item SET item.attribute.id = ?1 WHERE item.id in (?2,?3.....?N)) results in NullPointerException thrown by Hibernate when building parameter metadata
As seen on one of the most authoritative Hibernate sources, named parameters result in a misleading exception
Question is: how do I properly formulate a bulk update query using Spring's HibernateTemplate? As correctly reported by Mykong, HibernateTemplate automagically sets query parameters 0-based, but eventually the author got the program working with non-positional parameters without mentioning (or having at all) any warning.
I think that the recommended way to do that now a days is with Spring Data JPA. There is a getting started tutorial here.
So if you have an entity, you can add an interface that extends any of the reposiotry interfaces supported in SpringDataJpa and add a modifying query.
public interface CustomerRepository extends CrudRepository<Customer, Long> {
#Transactional
#Modifying
#Query("update Customer c set c.firstName = ?1 where c.id = ?2")
int updateNameById(String nameToUpdate, long id);
#Transactional
#Modifying
#Query("update Customer c set c.firstName = ?1 where c.id in (?2)")
int updateNameByIds(String nameToUpdate, List<Long> ids);
}
Then Spring will implement that method and you can use the it as:
customerRepo.updateNameByIds("newName", Arrays.asList(cust.getId()));
This will generate the following sql:
update customer set first_name=? where id in (?)
Here is the project I used to test with
In order to get the a record in an SQL table with a name, I am using the following query:
SELECT * FROM User WHERE User.name = name;
And the corresponding Spring JPA method name is the following:
UserEntity findUserByName(#Param("name") String name);
My question is the following:
How can I request a random record from an SQL table?
I know that my SQL query should be the following:
SELECT * FROM User
ORDER BY RAND()
LIMIT 1;
But, what should be the corresponding Spring JPA method name for that?
UserEntity findUserXXXXXXX (XXXXXXX);
JPA supports functions which are defined in specification. You can use native query option or JPA 2.1 function to call database functions which are not directly supported by the JPA specification. You can use #Query annotation in your spring data jpa repository.
Native Query
#Query(value="SELECT * FROM User ORDER BY RAND() LIMIT 1", nativeQuery = true)
UserEntity findUser();
Function
#Query("SELECT u FROM UserEntity u order by function('RAND')")
List<UserEntity> findUser();
You can use list.get(0) to get the single user.
if you want to random a list you can easily do it by using PagingAndSortingRepository and provide a random page number where (page_number < page_count)
e.g
long page_count = (totalRecords / perPage)
//Use PageRequest for PagingAndSortingRepository Pageable object
PageRequest.of(new Random().nextLong(page_count), perPage)
or you can provide the random page number from front_end side
In Hibernate, I created a query using JOIN to join two tables. The query executes fine in Oracles SQL Developer. However, if I add it to a #NamedQuery, the server starts with this error:
Error in named query: loadFooByAnother: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ON near line 1, column xxx
My named query is:
SELECT foo FROM FooTable foo JOIN BarTable bar
ON foo.something=bar.somethingId
WHERE bar.anotherId=:another
Is it not possible to use JOIN .. ON syntax in Hibernate?
You need to use the with directive, if you use HQL:
SELECT foo
FROM FooEntity foo
JOIN foo.bar b with b.name = :name
WHERE foo.prop = :prop
This is for supplying a custom ON clause. From your example, judging from how you joined tables, I think you tried to execute a native SQL using a #NamedQuery.
If you want to run a native SQL query, you have to use #NamedNativeQuery instead.
If you want to use HQL, you need to use Entities and to join Entity associations (not tables).
If you use JPQL then the with directive has to be replaced by the on directive, but again, you need to navigate entity associations, meaning you have to map them first.