I have severals queries stored in database, and my goal is to create a mybatis dao that execute a selected query from my list.
Does anyone have idea on how to do this ? (Just one dao able to execute a passed query as parameter)
This can be done by injecting variable verbatim using string substitution:
Mapper interface
List<Map<String, Object>> get(#Param("query") String query);
And xml mapping file:
<select id="get" resultType="hashmap" statementType="STATEMENT">
${query}
</select>
Related
I have a method -> findByfileNameLike(fileName,1, pageable) and its declaration in a repository that extends JPA Repository is
#Query(value = QUERY)
#Transactional(propagation = Propagation.REQUIRED, readOnly = true)
#LogExecutionTime
Page<BatchDTO> findByfileNameLike(String
fileName,#Param("departmentId")Integer departmentId, Pageable pageable)
Query is Select new DTO(bdm.id.batch.status) from Table bdm where bdm.id.departmentId =:departmentId and bdm.id.batch.status <> 7";
I want to filter the query by the column fileName.I have read to give the method name as given according to the doc of spring data jpa.But its not working.
Where and how will i give the fileName to be filtered?Should it be first parameter in the method?
Once you specify a query using the annotation #Query, Spring data jpa will not automatically create a query for you based on the method name and it will rely on the query provided by using the annotation.
The method findByfileNameLike will not make any difference here as a query is provided explicitly. Hope that answers your question
i would like to know if you have any idea how i can achieve this, considering a query stored as string in the configuration file.
I tried to use SqlQuery applied to the DBSet, but the problem is that SqlQuery requires me to select all properties of the required entities in my query. If i don't consider any column, it will complain because is not able to map the query to the entities.
I don't want to select all properties of the entities i want to query.
Thanks
If you are using EF then why not use Database.ExecuteSqlCommand()? It's in the System.Data.Entity namespace.
For example:
int result = db.Database.ExecuteSqlCommand("Non SELECT SQL etc...");
Well, I ended up implementing a mechanism using reflection that basically receives a group of fields to select, and constructs dynamic objects with those fields, so when applied the query with the joins between the entities, will only bring the fields I am looking for.
So, considering Entity1, Entity2, Entity3 with the following relationship
<b>Entity1</b>{
<br/> Entity1Name, <br/> List<*Entity2*> Entity2Items, <br/> etc..
<br/>}
and
<b>Entity2</b> { <br/> Entity2Name, <br/> List<*Entity3*> Entity3Items <br/>}
I can store e.g. the following query in the configuration file, and retrieve the information:
"Entity1.Entity1Name", <br/>
"Entity1.Entity2Items.Entity2Name", <br/>
"Entity1.Entity2Items.Entity3Items.Entity3Name"
Anyway, I was just trying to see if there would be any solution out-of-the-box that would require minimal code changes.
Thank you.
I'm trying to query a spring-data couchbase repository using N1QL queries. I have two doubts:
I'm using #Query annotation to generate queries, my code looks like this:
#Query("#{#n1ql.selectEntity} WHERE $0 = $1 AND #{#n1ql.filter}")
public Page<GsJsonStore> matchJson(String term, String value, Pageable pageable);
//Query
Page<GsJsonStore> p = repo.matchJson("_object.details.status", "ready", pg);
This query doesn't return any results. However, when I run the same query (below) in cbq I get the desired result:
select * from default where _object.details.status = 'ready';
How can I view the query string generated by the Couchbase repository? I'm using spring-boot. Am I correct in using the #Query annotation for this use-case?
Also, how can I perform n1QL queries on CouchbaseOperations template? I know that there's a findByN1QL method, but I didn't find any good documentation about it. Could someone please explain how to use this?
The query looks ok. You did persist your GsJsonStore entities using the Spring Data Couchbase repository did you?
In order to log all the queries generated and executed by the framework (including inline queries like in your case), you can configure the logger like so in a logback.xml configuration:
<logger name="org.springframework.data.couchbase.repository.query" level="debug"/>
You'll see that the query that got executed and the query that you ran in cbq are not the same, since at least you didn't use a WHERE clause.
In CouchbaseOperations there are two methods relative to N1QL queries:
findByN1QL: this expects specific structure of the query, in order to make sure all data necessary to correct deserialization of a Spring Data annotated entity is selected (which is the purpose of the #n1ql.selectEntity and #n1ql.filter SpEL).
findByN1QLProjection is more free-form. If Jackson can deserialize the results of the provided query to the requested Class, then it will. As such, the SELECT clause is much less implicitly restricted in this method.
To use both, you must pass in a N1qlQuery object from the SDK. Such queries can be constructed using factory methods of the N1qlQuery class, for example:
//a version of the query that is constructed from positional parameters
N1qlQuery queryWithParameter = N1qlQuery.parameterized("SELECT name FROM `beer-sample` WHERE name LIKE $0", JsonArray.from("%dog%"));
//let Spring Data execute the query, projecting to the String class
List<String> beerNamesContainingDog = template.findByN1QLProjection(queryWithParameter, String.class);
We have a use case where a user can pass in arbitrary search criteria for a collection, and wants the output paged. Using Spring Data repositories, this is quite simple if we know ahead of time what attributes they may be searching on by simple extending MongoRepository, and declaring a:
Page<Thing> findByFooAndBarAndBaz(Type foo, Type bar, Type baz, Pageable page)
However, if we generate the query ourselves either using the fluent interface or constructing a mongo string and wrapping it in a BasicQuery class, I can not find a way to get that into a repository instance. There is no:
Page<Thing> findByQuery(Query q, Pageable page)
functionality that I have been able to see.
Nor can I see how to hook into the MongoTemplate querying functionality with the Page abstraction.
I'm hoping I don't have to roll my own paging (calculating skip and limit parameters, which I guess is not hard) and call into the template directly, but I guess I can if that's the best choice.
I don't think this can be done in the way I'd hoped, but I've come up with a workaround. As background, we put all our methods to do data access in a DAO, and some delegate to the repository, some to the template.
Wrote a DAO method which takes our arbitrary filter string (which I have a utility that converts it to standard mongo JSON query syntax.
Wrap that in a BasicQuery to get a "countQuery".
Use that countQuery to get a total count of records using MongoTemplate#count(Query, Class)
Append my paging criteria to create a "pageQuery" using Query#with(Pageable)
Run the pageQuery with MongoTemplate#find(Query, Pageable)
Get the List<T> result from that, the Pageable that was used for the query and the count returned from the countQuery run, and construct a new PageImp to return to the caller.
Basically, this (DocDbDomain is a test domain class for testing out document db stuff):
Query countQuery = new BasicQuery(toMongoQueryString(filterString));
Query pageQuery = countQuery.with(pageRequest);
long total = template.count(countQuery, DocDbDomain.class);
List<DocDbDomain> content = template.find(pageQuery, DocDbDomain.class);
return new PageImpl<DocDbDomain>(content, pageRequest, total);
You can use the #Query annotation to execute an arbitrary query through a repository method:
interface PersonRepository extends Repository<Person, Long> {
#Query("{ 'firstname' : ?0 }")
Page<Person> findByCustomQuery(String firstname, Pageable pageable);
}
Generally speaking, #Query can contain any JSON query you can execute via the shell but with the ?0 kind of syntax to replace parameter values. You can find more information on the basic mechanism in the reference documentation.
In case you can't express your query within the #Query-Annotation, you can use the Spring Repository PageableExecutionUtils for your custom queries.
For example like this:
#Override
public Page<XXX> findSophisticatedXXX(/* params, ... */ #NotNull Pageable pageable) {
Query query = query(
where("...")
// ... sophisticated query ...
).with(pageable);
List<XXX> list = mongoOperations.find(query, XXX.class);
return PageableExecutionUtils.getPage(list, pageable,
() -> mongoOperations.count((Query.of(query).limit(-1).skip(-1), XXX.class));
}
Like in the original Spring Data Repository, the PageableExecutionUtils will do a separated count request and wrap it into a nice Page for you.
Here you can see that spring is doing the same.
Is it possible to add an OrderBy clause in to JPA Named query at runtime?
Named queries are processed by the persistence provider when the EntityManagerFactory is created. You can't change/modify/append anything about a named query dynamically at runtime.
If you are using JPA 2.0 and you need a way to do high-performance dynamic queries at runtime, you should look into the Criteria API.
From Java EE 5 Documentation : "Is used to specify a named query in the Java Persistence query language, which is a static query expressed in metadata. Query names are scoped to the persistence unit".
As it says, it is static & you can't change the query at runtime.
Rather use custom query or if ordering element is fixed then you can use annotation;
Field:
#OrderBy(value="nickname")
List<Person> friends;
Method:
#OrderBy("nickname ASC")
public List<Person> getFriends() {...};
Even if you can't add order-by clause to your named query, you can provide a parametric orderBy. The following is a perfectly valid query:
SELECT u FROM User u ORDER BY :orderBy
And you are going to change ordering with something like:
query.setParameter("orderBy", "id");