fetching single column values in JPA - java

I want to get all the values from a particular column in JPA and store all values into a list. currently, I am using the below approach but I am getting records in something else format.can someone please help me out
Query q1 = factory.createNativeQuery("select * from booking_attendee where booking_id="+id);
List<String> em1=q1.getResultList();
return em1;
query otput
em=[[Ljava.lang.Object;#68606667, [Ljava.lang.Object;#2cd7f99a, [Ljava.lang.Object;#137a5a5, [Ljava.lang.Object;#a45cc1c, [Ljava.lang.Object;#61fdc06d, [Ljava.lang.Object;#72f5eee1, [Ljava.lang.Object;#4e536797]

If you want to create a native query for this, it is more about how to solve this in SQL. You do not say SELECT * which means all columns. You would have to say SELECT your_column_name to select only a specific column.
Query q1 = factory.createNativeQuery("SELECT your_column FROM booking_attendee");
List<String> em1 = q1.getResultList();
The WHERE clause could and should be defined with the parameter binding of JPA. There are several advantages concerning performance and SQL injection.
Named parameter binding is special to the persistence provider (e.g. Hibernate). The common way for JPA is using ? to let your code be portable to other providers.
Query q1 = factory.createNativeQuery("SELECT your_column FROM booking_attendee b WHERE b.booking_id = ?");
q1.setParameter(1, id);
List<String> em1 = q1.getResultList();
Native queries offer the possibilities to use original SQL. Like this, some features which are specific for your database could be used with this. Nevertheless, if you do not have very specific SQL code, you should also have a look in JPQL, the specific query language of JPA, and the JPA Criteria API which offers advantages when you want to refactor your code, shows errors during compile time and makes the dynamic creation of queries easier.

Related

Is there a way to dynamically generate Spring Data Jpa queries?

I'm writing an app using Spring Boot, Spring Data. And I'm trying to implement a filtering feature based on different filter parameters.
Using Spring Data queries we can define quite complex logic, e.g.:
#Query("SELECT u FROM User u WHERE u.status = 1")
Collection<User> findAllActiveUsers();
But what if the number of where clauses, order, limit, number of different parameters are unknown till we make an actual filter request which can be quite complex.
Right now filter params are send in a json object which I parse and retrieve them and the result sql query can be something like this:
SELECT * FROM table
WHERE field1 != `value1` and (field1 != ` value2 `OR (field1 = `value3` AND filed2 < 3))
AND field2 != 99
Is it possible to generate dynamically complex queries with undefined (till the actual filter request, during runtime) number of params, where clauses and other stuff?
I use this active project RSQL for JPA
https://github.com/perplexhub/rsql-jpa-specification
Sometime back I wrote an article on Spring Data JPA Query with Dynamic Where Clause. In this example you can send a Where Clause and Map of parameters for that. You can make use of this and modify it a bit suit your needs.
I would suggest using Spring JPA Specification
ref : https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
To build it in a type safe manner, you can use FluentJPA.

How to use the same Java class with different SQL queries

I'm designing a Java report application that can receive any SQL query(on a already defined database) and then I display the result in a table grid in a Vue.js application.
I have some doubts on how to load a Java generic/hybrid class that can fit differents SQL queries.
I mean, is it possible to create a class in Java that can change/mutate during runtime so I can map different SQL queries in it?
I know that it is possible to use the java.sql.ResultSetMetaData to get the column name, table name, column class name, etc. (I don't know if it possible with hibernate)
But I don't know how to map the results in a unique class.
For example:
I have 3 differents queries and they could be a lot more:
1) SELECT ID, COUNTRY_NAME FROM COUNTRY;
2) SELECT CODE, NAME, PRICE FROM PRODUCT;
3) SELECT P.CODE, P.NAME, S.NAME
FROM PRODUCT P
JOIN SUPPLIER S
ON S.ID = P.SUPPLIER_ID
WHERE P.PRICE > 25;
I need to map this query results(one at a time obviously) in a generic class so then I pass it to the Vue app to display it in a grid.
Is it a way to do that?
Don't reinvent the wheel and use what is already available and what is well tested.
What you're looking for is called Spring JDBC, or, for an even higher level, Java Persistence API.
Using Spring JDBC to extract a set of records might look like
final List<YourClass> results =
jdbcTemplate.queryForList(
"Native SQL statement",
queryArguments,
YourClass.class
);
Using a JPA implementation (e.g. Hibernate, EclipseLink, ObjectDb), the operation might look like
final TypedQuery<YourClass> query = entityManager.createQuery("JPQL statement", YourClass.class);
final List<YourClass> results = query.getResultList();

How a clause (order by) can be removed from a jOOQ query

Is possible to remove a clause (the order by clause in my case) from a dynamically constructed query in jOOQ.
Suppose that after creating the query:
DSLContext create = DSL.using(SQLDialect.POSTGRES);
SelectQuery<Record> query = create.select().from("myTable").where("fk = 1").orderBy(DSL.field("pk")).getQuery();
System.out.println(query.getSQL());
// select * from myTable where (fk = 1) order by pk asc
I want to change the order by clause or remove it to get only
select * from myTable where (fk = 1)
Is possible make this with jOOQ?. If is not possible and anyone knows a query builder library that allows this will be also welcome.
This currently cannot be done through the public API. In a future jOOQ 4.0, there might be a cleaner separation of the DSL API and the Model API, where such a model API would allow you to freely manipulate all your query parts, including removing objects again from SELECT clauses.
Right now, you have at least two options to implement dynamic SQL:
Don't add the ORDER BY clause until you know whether you need it:
SelectQuery<?> select = create
.select()
.from("myTable")
.where("fk = 1")
.getQuery();
if (someCondition)
select.addOrderBy(DSL.field("pk"));
Alternative piece of logic:
List<SortField<?>> orderBy = new ArrayList<>();
if (someCondition)
orderBy.add(DSL.field("pk").asc());
create.select()
.from("myTable")
.where("fk = 1")
.orderBy(orderBy);
Post-process / transform your query using an ExecuteListener or a VisitListener. This is more of a workaround in edge-cases, though.
In your particular case, you should probably go with option 1. Another, more functional approach to tackling dynamic SQL generation is documented here.

Dynamic Named Query in Entity class using JPQL example

I have a named query as below;
#NamedQuery(name = "MyEntityClass.findSomething", query = "SELECT item FROM MyTable mytbl")
Now I want to append dynamic sort clause to this query (based on UI parameters)
Can I get an example using JPQL for doing the same (like how to set a dynamic ORDER BY in the Entity class)
I have already tried using CriteriaQuery, but was looking for a JPQL implementation now.
NamedQueries are by definition NOT dynamic, it is not correct to change them programmatically.
So the way to go is to create a JPQL query (but not a named query) like this:
TypedQuery<MyEntity> query = em.createdQuery("SELECT item FROM MyEntity item ORDER BY "+sortingCol, MyEntity.class);
On the other hand, if you REALLY want to use the named query, you could do that the following way:
#NamedQuery(name = "MyEntityClass.findSomething", query = MyEntity.NAMED_QUERY)
#Entity
public class MyEntity {
public static final NAMED_QUERY= "SELECT item FROM MyTable mytbl";
//+your persistent fields/properties...
}
//and later in your code
TypedQuery<MyEntity> query = entityManager.createQuery(MyEntity.NAMED_QUERY + " ORDER BY " + sortingCol, MyEntity.class);
Complementing for JPA 2.1
As of JPA 2.1 it is possible to define named queries programmatically.
This can be achieved using entityManagerFactory.addNamedQuery(String name, Query).
Example:
Query q = this.em.createQuery("SELECT a FROM Book b JOIN b.authors a WHERE b.title LIKE :title GROUP BY a");
this.em.getEntityManagerFactory().addNamedQuery("selectAuthorOfBook", q);
// then use like any namedQuery
Reference here
This can be useful, for instance, if you have the orderby field defined as a application parameter. So, when the application starts up or on the first run of the query, you could define the NamedQuery with the defined OrderBy field.
On the other side, if your OrderBy can be changed anytime (or changes a lot), then you need dynamic queries instead of NamedQuery (static). It would not worth to (re)create a NamedQuery every time (by performance).
#NamedQuery
Persistence Provider converts the named queries from JPQL to SQL at deployment time.
Until now, there is no feature to create/update the query with #NamedQuery annotation at runtime.
On the other hand, you can use Reflection API, to change the annotation value at runtime. I think It is not solution, also it is not you wanted .
em.createQuery()
Persistence Provider converts the dynamic queries from JPQL to SQL every time it is invoked.
The main advantage of using dynamic queries is that the query can be created based on the user inputs.

JPA Query toString

I have a JPA Query I am executing on the Google App-Engine datastore.
I am building the query using parameters.
After all parameters have been inputted, I wish to view the Query String.
That is, I wish to view the actual query being executed by the datastore.
Is that even possible?
It would really help me in debugging.
To SOLVE the question, assume the following query:
Query query=EM.createQuery("SELECT FROM "
+MyClass.class.getName()+" C WHERE C.field = :arg1");
query.setParameter("arg1", someParam);
if System.out.println(SomeObj) prints 'SELECT FROM MyClass C WHERE C.field = 17'
then the question is solved.
David
That is, I wish to view the actual query being executed by the datastore.
Enabling DEBUG for the DataNucleus.Datastore log category should do it. Check the DataNucleus Logging documentation.
In current DataNucleus you can just call toString() on the JPA Query object to see the single-string form (without parameter substitution). The actual query invoked on the datastore depends on the datastore (obviously), being SQL in the case of RDBMS, and something else in the case of BigTable.

Categories