Select single item from database with Spring Hibernate Sessionfactory - java

This is in my DAO:
public List<Weather> getCurrentWeather() {
return sessionFactory.getCurrentSession().createQuery("from Weather").list();
}
This gets all of the elements from table Weather. But lets say I wanna do something like this(I want only one element from table Weather):
public Weather getCurrentWeather() {
return sessionFactory.getCurrentSession().createQuery("from Weather where id = 1").list(); // here should be something else than list()
}
I know there should not be list() in the end, but what must I write there, to get only one object?

If you have an id, you just use get:
public Weather getCurrentWeather() {
return sessionFactory.getCurrentSession().get(Weather.class, 1);
}
If you do need to do a query, yeah you'll have to grab the top of the result set, or you can use uniqueResult() on the query.

Is there something wrong with getting a list? :) Even if you know there is only 1 hibernate cannot assume that. Getting a list is safer anyway!
public Weather getCurrentWeather() {
List<Weather> list = sessionFactory.getCurrentSession().createQuery("from Weather where id = 1").list(); // here should be something else than list()
return (list.isEmpty() ? null : list.get(0));
}

You need to use the Criteria API as below:
List<LeaveManagement> leaveManagements = session.createCriteria(LeaveManagement.class)
.add( Restrictions.isNull("approvedTimeStamp") )
.uniqueResult();
If you want to write a hql query you can write as:
String hql = "from LeaveManagement where approvedTimeStamp is null";
Query query = session.createQuery(hql);
LeaveManagement results = (LeaveManagement) query.uniqueResult();

Related

How to return deleted rows using jdbi?

How do I return the deleted rows using jdbi? For example, I'd like to do something like this:
public List<User> deleteAndReturnUsers() {
return jdbi.withHandle(handle -> {
return handle.createQuery("DELETE FROM mytable where id = :id")
.bind("id", "someid")
.map(new UserMapper())
.list();
});
}
Postgresql has a returning keyword...
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=25d284309745e40c8ea29945481d1aa2
DELETE FROM data WHERE val >= 2 RETURNING *;
You can then execute that query in the same way as you would a normal SELECT statement, and get a result set back; containing the records deleted.

Mapping projection form hibernate HQL query into object

I am returning only a few columns from a table in DB:
List<MyClass> l = (List<MyClass>) session.createQuery("Select p.one, p.two FROM MyClass p WHERE p.id IN :id")
.setParameter("userId", id)
.list();
However, the query returns List of arrays, e.g
l.get(0) // [0] is object representing p.one in query, [1] p.two
Is there a hibernate some effective way how to map it to MyClass object? So the query would actually return list of MyClass objects where selected properties would have values, others would be set to null?
I have read about new MyClass(arg1,arg2) way in the query with construtor, however i have also read it is ineffective.
Thanks for help!
You can use try catch block and use query.getSingleResult() to return Object.
Query query = em.createNativeQuery("FROM TipoUsuario WHERE NAME = :name;", TipoUsuario.class)
.setParameter("name", name);
TipoUsuario tipoUsuario = null;
try
{
tipoUsuario = (TipoUsuario) query.getSingleResult();
}
catch ( Exception e )
{
return null;
}
createNativeQuery is just a sample. You can use createNamedQuery instead and put HQL in Entity with annotation #NamedQueries.
If you want to create MyClass you just need to use the fully-qualified name of the class in your query, e.g.
SELECT NEW my.pack.MyClass(p.one, p.two) FROM MyClass p WHERE p.id IN :id
I haven't heard of this being ineffective, and I can't image why it would be. It's just calling the constructor on the result instead of returning it as an array or object. Overall, it's probably a very good way of fetching, since you only select the fields that you need.
This and other options are also explained in more detail here.

How to do a .filter() in hibernate

In the django orm I can do something like the following:
people = Person.objects.filter(first_name='david')
for person in people:
print person.last_name
How would I do the equivalent in Java Hibernate's orm? So far, I've been able to do a single get, but not a filter clause:
Person p = session.get(Person.class, "david");
What would be the correct way to do this though?
you can use native SQL
session.beginTransaction();
Person p = getSingleResult(session.createNativeQuery("SELECT * FROM People where name = 'david'",Person.class));
session.getTransaction().commit();
and the function getSingleResult would be somthing like this :
public static <T> T getSingleResult(TypedQuery<T> query) {
query.setMaxResults(1);
List<T> list = query.getResultList();
if (list == null || list.isEmpty()) {
return null;
}
return list.get(0);
}
you can get a list like this :
List<Person> list = session
.createNativeQuery("SELECT * FROM People", Person.class)
.getResultList();
There are several approaches to do this so here goes:
Lazy way - possibly bad if you have a tons of data is to just load up
the whole list of persons, stream it and apply a filter to it to
filter out objects not matching the given first name.
Use a HQL query (Hibernate Query Language) to create a select query
https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/chapters/query/hql/HQL.html
Use Hibernate's Criteria API to achieve the above
https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/chapters/query/criteria/Criteria.html
Alternatively you can even use a native SQL query to do the above.

Jpa named query: how to get a list of column

I have an entity orderdetails, where a user can have many ordernames I want to get all the ordername by userid using jpa named query. I tried this
SELECT o.orderName FROM OrderDetails o WHERE o.userId=:userId;
Since the return type will be List in the resultset, I executed the query like this
getEntityManager().createNamedQuery("getOrderNamesByUserId",
orderDetail.class).setParameter("userId", userId);
This obviously is not working. How can I get that query working? One way is to iterate the List but I wonder whether there is another way around?
Well this is non-compiled code snippet, you could try the following approach.
#Override
public List<OrderDetails> findOrders(Long userId) {
TypedQuery<OrderDetails> query = entityManager.createNamedQuery(
"OrderDetails.getOrderNamesByUserId", OrderDetails.class);
query.setParameter("userId", userId);
List<OrderDetails> list = query.getResultList();
return list;
}
If you just need to select one column(ordername), use getResultList() method.
Query query = getEntityManager().createNamedQuery("getOrderNamesByUserId", OrderDetail.class);
query.setParameter("userId", userId);
List<String> orderNameList = query.getResultList();

JPA Query.getResultList() - use in a generic way

I'm creating a complex query with multiple tables and need to list the result. Usually, I'm using the EntityManager and map the result to the JPA-Representation:
UserEntity user = em.find(UserEntity.class, "5");
Then I can access all values as the user UserEntity class defines it. But how can I access the field-values returned from a native, multiple-table query? What I get is a List of Objects. That's fine so far, but what "is" that Object? Array? Map? Collection? ...
//simpleExample
Query query = em.createNativeQuery("SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id");
List list = query.getResultList();
//do sth. with the list, for example access "something" for every result row.
I guess the answer is quite simple, but most examples out there just show the usage when directly casting to a targetClass.
PS: In the example I could use the class-mappings of course. But in my case someTable is not managed by JPA, and therefore I don't have the entity nor do I have a class-representation of it, and since I'm joining like 20 tables, I don't want to create all the classes just to access the values.
General rule is the following:
If select contains single expression and it's an entity, then result is that entity
If select contains single expression and it's a primitive, then result is that primitive
If select contains multiple expressions, then result is Object[] containing the corresponding primitives/entities
So, in your case list is a List<Object[]>.
Since JPA 2.0 a TypedQuery can be used:
TypedQuery<SimpleEntity> q =
em.createQuery("select t from SimpleEntity t", SimpleEntity.class);
List<SimpleEntity> listOfSimpleEntities = q.getResultList();
for (SimpleEntity entity : listOfSimpleEntities) {
// do something useful with entity;
}
If you need a more convenient way to access the results, it's possible to transform the result of an arbitrarily complex SQL query to a Java class with minimal hassle:
Query query = em.createNativeQuery("select 42 as age, 'Bob' as name from dual",
MyTest.class);
MyTest myTest = (MyTest) query.getResultList().get(0);
assertEquals("Bob", myTest.name);
The class needs to be declared an #Entity, which means you must ensure it has an unique #Id.
#Entity
class MyTest {
#Id String name;
int age;
}
The above query returns the list of Object[]. So if you want to get the u.name and s.something from the list then you need to iterate and cast that values for the corresponding classes.
I had the same problem and a simple solution that I found was:
List<Object[]> results = query.getResultList();
for (Object[] result: results) {
SomeClass something = (SomeClass)result[1];
something.doSomething;
}
I know this is defenitly not the most elegant solution nor is it best practice but it works, at least for me.
Here is the sample on what worked for me. I think that put method is needed in entity class to map sql columns to java class attributes.
//simpleExample
Query query = em.createNativeQuery(
"SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id",
NameSomething.class);
List list = (List<NameSomething.class>) query.getResultList();
Entity class:
#Entity
public class NameSomething {
#Id
private String name;
private String something;
// getters/setters
/**
* Generic put method to map JPA native Query to this object.
*
* #param column
* #param value
*/
public void put(Object column, Object value) {
if (((String) column).equals("name")) {
setName(String) value);
} else if (((String) column).equals("something")) {
setSomething((String) value);
}
}
}
What if you create a bean with all required properties and cast the result using Java 8+ streams?
Like this:
public class Something {
private String name;
private String something;
// getters and setters
}
And then:
import javax.persistence.Query;
...
Query query = em.createNativeQuery("SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id", Something.class);
List<?> list = query.getResultList();
return list
.stream()
.map(item -> item instanceof Something ? (Something) item : null)
.collect(Collectors.toList());
That way, you don't need to return List<Object[]> nor hide the warning with #SuppressWarnings("unchecked")
Ps.:
1 - I know that this post is very old. But... I'm here in 2021, so others will be coming here too =)
2 - This is wrong or bad practice? Let me know :D
You can also update your hibernate to a version greater than 5.4.30.final

Categories