Hibernate: Fetching columns with their aliases - java

Consider this trivial query:
SELECT 1 as first, 2 as second
When using Hibernate we can then do something like:
em.createNativeQuery(query).fetchResultList()
However, there seem to be no way of getting the aliases (or column names). This would be very helpful for creating List<Map<String, Object>> where each map would be a row with their aliases, for instance in this case: [{first: 1, second: 2}].
Is there a way to do something like that?

I would suggest a bit different approach which may meet your needs.
In JPA 2.1 there is a feature called "result set mapping".
Basically you have to define a POJO class which would hold the result values (all the values must be passed using the constructor):
public class ResultClass{
private String fieldOne;
private String fieldTwo;
public ResultClass(String fieldOne, String fieldTwo){
this.fieldOne = fieldOne;
this.fieldTwo = fieldTwo;
}
}
Then you have to declare the mapping on one of your entities (does not matter on which, it just has to be a declated #Entity):
#SqlResultSetMapping(name="ResultMapping", classes = {
#ConstructorResult(targetClass = ResultClass.class,
columns = {#ColumnResult(name="columnOne"), #ColumnResult(name="columnTwo")})
})
The columnOne and columnTwo are aliases as declared in the select clause of the native query.
And finally use in the query creation:
List<ResultClass> results = em.createNativeQuery(query, "ResultMapping").getResultList();
In my opinion this is more elegant and "a level above" solution as you are not working with a generic Map key/values pairs but with a concrete POJO class.

You can use ResultTransformer interface . Implement custom mapper for mapping values with aliases.
here is example https://vladmihalcea.com/why-you-should-use-the-hibernate-resulttransformer-to-customize-result-set-mappings/
with ResultTransformer you can easy customize result set type , especially if you need aliases

Related

How to Query-By-Example with IN clause in spring-jpa?

I have a spring-jpa application and fetching rows from database with query-by-example like:
public List<Person> query() {
Person p = new Person();
person.name = "john";
return dao.findAll(Example.of(p));
}
Problem: I want to add an IN clause, like:
WHERE person.name IN ('john', 'jane');
Essentially, an IN clause is the same as an OR matching on a specific field.
So I could achieve the same with person.name = 'john' OR person.name = 'jane'.
BUT: how can I add those conditions into an example object that obviously has no list property?
As #Hitham S. AlQadheeb and #pirho hinted at, this is not supported by Query By Example. The documentation explicitly states:
Currently, only SingularAttribute properties can be used for property matching.
Use an alternative like Derived Queries, Specifications or a custom method implementation.

Spring data Derived Queries with Multiple Condition and one parameter

How can I create a derived query methods in Spring data which select result based on multiple conditions but with only one parameter.
List<Entity> findById1OrId2OrId3(String id1OrId2OrId3);
Something like this example.
I don't think it is possible with derived queries.
Alternatively,
#Query("from Entity e where e.id1 = ?0 or e.id2 = ?0 or e.id3 = ?0")
List<Entity> findById1OrId2OrId3(String singleId);
You can use "In" and make list of Ids then make a new derived query to achieve this

Jdbi - how to bind a list parameter in Java?

We have an SQL statement which is executed by Jdbi (org.skife.jdbi.v2). For binding parameters we use Jdbi's bind method:
Handle handle = ...
Query<Map<String, Object>> sqlQuery = handle.createQuery(query);
sqlQuery.bind(...)
However we have a problem with in-lists and currently we are using String.format for this. So our query can look like this:
SELECT DISTINCT
tableOne.columnOne,
tableTwo.columnTwo,
tableTwo.columnThree
FROM tableOne
JOIN tableTwo
ON tableOne.columnOne = tableTwo.columnOne
WHERE tableTwo.columnTwo = :parameterOne
AND tableTwo.columnThree IN (%s)
%s is replaced by String.format so we have to generate a proper string in java code. Then after all %s are replaced we are using jdbi's bind method to replace all other parameters (:parameterOne or ?).
Is there a way to replace String.format with jdbi? There is a method bind(String, Object) but it doesn't handle lists/arrays by default. I have found this article which explains how to write our own factory for binding custom objects but it looks like a lot of effort, especially for something that should be already supported.
The article you linked also descibes the #BindIn annotation. This provides a general purpose implementiation for lists.
#UseStringTemplate3StatementLocator
public class MyQuery {
#SqlQuery("select id from foo where name in (<nameList>)")
List<Integer> getIds(#BindIn("nameList") List<String> nameList);
}
Please note that you'll have to escape all pointy brackets < like this \\<. There is a previous discusion on SO: How to do in-query in jDBI?
I just wanted to add an example since I recently spent considerable time getting a slightly more complex scenario to work :
Query :
select * from sometable where id <:id and keys in (<keys>)
What worked for me :
#UseStringTemplate3StatementLocator
public interface someDAO {
....
....
// This is the method that uses BindIn
#Mapper(someClassMapper.class)
#SqlQuery("select something from sometable where age \\< :age and name in (<names>)")
List<someclass> someMethod (#Bind("age") long age, #BindIn("names") List<string> names);
#Mapper(someClassMapper.class)
#SqlQuery("select something from sometable where id = :id")
List<someclass> someMethod1 (#Bind("id") long id);
...
...
}
Note: I did have to also add the below dependency since I am using
#UseStringTemplate3StatementLocator
<dependency>
<groupId>org.antlr</groupId>
<artifactId>stringtemplate</artifactId>
<version>3.2.1</version>
</dependency>
The main thing to observe in the above example : You only need to escape the less than operator (i.e. < ) and not the <> that surround the collection variable (names).
As you can see I did not use a sql.stg file to write my queries in. Initially I incorrectly assumed that when using #UseStringTemplate3StatementLocator , we have to write the queries in the sql.stg file. However, somehow I never got my sql.stg file to work and I eventually reverted back to writing the query within the DAO class using #SqlQuery.
For the most recent jdbi version things got easier:
public interface MyDao {
#SqlQuery("select id from foo where name in (<nameList>)")
List<Integer> getIds(#BindList("nameList") List<String> nameList);
}
#BindIn → #BindList, and no longer requires StringTemplate
Reference: https://jdbi.org/

Possible to query by key instead of value in Hazelcast (using Predicates)?

In Hazelcast, is it possible to query an IMap based on attributes of a key instead of the values? All the Hazelcast examples show querying by value. E.g., for a map of employees with keys that are strings:
IMap<String, Employee> employees;
The typical search predicates then search based on employee attributes (name, salary, etc). But my case uses more complex keys, such as:
IMap<DataAttributes, DataValue> myData;
So if DataAttributes has fields such as:
class DataAttributes {
String theDescription;
Date theStartTime;
public String getDescription() { return theDescription; }
// etc....
}
I want to write a predicate that can query by the keys, to return an appropriate DataValue object. This does not work:
Predicate pred = Predicates.equal("description", "myDescription");
myData.keySet(pred); // Throws IllegalArgumentException: "There is no suitable accessor for..."
I could roll-my-own as suggested in this answer, but I'd rather use an out-of-the-box solution if I can.
It doesn't matter if I wind up using the Criteria API, or the Distributed SQL Query API. Any working query would be great. Bonus points for a solution that works on nested attributes (i.e.: DataAttributes theStartTime.getYear()).
It is possible using PredicateBuilder (com.hazelcast.query.PredicateBuilder). The PredicateBuilder paradigm allows you to query based on keys, like so:
EntryObject eo = new PredicateBuilder().getEntryObject();
Predicate fredWithStartTimeThisYear = eo.key().get("Description").equal("Fred")
.and(eo.key().get("theStartTime.Year").equal(2015));
Note that you can refer to class members by accessor method ("getter") or field name, as you can see in the above example code. I found this information in the "Mastering Hazelcast" online book, available at hazelcast.org (but you have to fill out a registration form to gain access to it).

Java Enums with different number of parameters

I want to create an enum that represents various JPA NamedQueries. Each query though may have a different number/type of parameters. So I when I want to refer to the query / query placeholder I can do something like the following:
Entity.Queries.FIND_PERSON_BY_NAME_AND_ADDRESS.toString(); //gets the Query itself
Entity.Queries.Query1.FIND_PERSON_BY_NAME_AND_ADDRESS.PLACEHOLDER_NAME ; //gets the string of the placeholder "name"
Entity.Queries.Query1.FIND_PERSON_BY_NAME_AND_ADDRESS.PLACEHOLDER_ADDRESS; //gets the String of the placeholder "address"
I want to do this so when I create the named queries I can do the following
Query q = entitiManager.createNamedQuery(Entity.Queries.FIND_PERSON_BY_NAME_AND_ADDRESS.toString);
q.setParameter(Entity.Queries.Query1.FIND_PERSON_BY_NAME_AND_ADDRESS.PLACEHOLDER_ADDRESS, address);
Is this possible with enums, or should I just use final constants in private static classes or something?

Categories