How to retrieve all primary keys of a table using hibernate? - java

I need to retrieve all primary keys of a table and put them in a list.
Any method that I have found so far let me retrieve each record as an object, which force me to retrieve their primary keys separately and add them to the list.
Is there any other approach to retrieve the primary keys of a table and adding them to a list?
Using the following code hibernate returns objects but I need it to return a list of primary keys to store them in pk list.
List pk = new ArrayList():
Criteria criteria = session.createCriteria(MyTable.class, "mytable");
pk = criteria.list();
if mytable is as following
id name value
1 a z4
2 f o2
pk list should be
[1,2]

You can simply create an HQL query that returns the field you want:
session.createQuery("SELECT mt.id FROM MyTable mt").list();
assuming your primary key field is named id and MyTable is your entity. You can also do it with Criteria and Projections.

There are generally there ways to achieve that
1) Using Criteria API
2) Using HQL
3) Using Native Query
From the above hibernate queries way , better to us (1) and (2) , the 3rd way has dependency on the type of database.
1) Using Criteria API
Criteria criteria = session.createCriteria(MyTable.class, "mytable");
criteria.setProjection( Projections.projectionList().add( Projections.property("mytable.id"), "mytable.id"));
List<Long> ids=criteria.list();
2) Using HQL
Solution is already explained by Sotirious
3) Using Native Query
session.createSQLQuery(" SELECT mytable.id FROM MyTable mytable ").addScalar("ID","Hibernate.LONG").list();

Another approach is to use finder queries directly on repository(Spring JpaRepository) methods.
public interface MyRepository extends JpaRepository<MyTable, KeyType> {
#Query("select mt.id from MyTable mt")
List<KeyType> getAllIds();
}

Related

Spring Boot JPA Query with Multiple column Condition and IN clause with combination of two columns

I have a Employee class and DB Table- Employee(Empid,Empname,EmpSalary,EmpJoiningDate)
Another class EmpData(Empid,EmpJoiningDate)
I have list , List<EmpData> empdata = new ArrayList();
Need to fetch all records from employee table with this combination using the empdata list,
This query I need to run for all combinations from List using JPA
For single combination below query works fine.
#query(value="select * from employee where empid=:empid and empJoiningDate=:empJoiningDate")
List<Employee> fetchEmpData(#param("empid") String empid,#param("empJoiningDate") String empJoiningDate)
instead of firing a separate query for each (empid, empJoiningDate ) combination, i need to fire a single query for all (empid, empJoiningDate ) combinations present in list . Is there any way to do this ?
Help me to revise the above query to run on the list.
If I assume Empid as primary key then why are you going for query. You already have your result set in your parameters.
So Your question is unclear. Relations are not defined.
I assume that you need to only two fields from DB to map into your EmpData Class and Empid and EmpJoiningDate has ManyToMany relation.
then use
#query(value="select Empid, EmpJoiningDate from employee where empid=:empid
and empJoiningDate=:empJoiningDate", nativeQuery = true)
List<EmpData> fetchEmpData(#param("empid") String
empid,#param("empJoiningDate") String empJoiningDate)

VO and DAO, How to design classes and execute query

I have a 3 tables:
Item: item_id (pk), short_description, ...
SupplierItem: item_id (fk), supplier_id (fk), vendor_product_number, ...
Supplier: item_supplier (pk), name, ...
Relation between Item and Supplier is many to many. SupplierItem is
intermediate table.
I want use VO and DAO.
How to design this in VO (Java)?
After, How can I do the following query in java code.
select i.item_id, i.short_description, s.vendor_product_number as FONUA_PRODUCT_CODE
from item i
left join supplier_item s
on i.item_id=s.item_id
where ((i.item_id=:item_id) OR :item_id IS NULL)
and i.parent_item_id is null
order by vendor_product_number DESC"
I still do not understand the concept in use VO and DAO.
Thanks
DAO would be the java file where you define your query and get the results of the query call on the database.
The results from the query will be saved by setting them as values to the properties of a particular VO.
For Example:
Your query returns ,
item_id, short_description, vendor_product_number
So let us say that you will have to create another java file say ItemVO.java and declare the particular properties of the ItemVO object,
For Ex:
private String itemId;
private String shortDescription;
private String vendorShortNum;
/*Define your getters and setters*/
In the DAO file you will have to map the query results to the VO file's objects.
ItemVO itemVO= new ItemVO();
itemVO.setItemId(/*the particular column value from the query result*/);
itemVO.setShortDescription(/*the particular column value from the query result*/);
itemVO.setVendorShortNum(/*the particular column value from the query result*/);

How to load multiple Hibernate entities in order of the identifiers or Primary Keys

How do we load multiple entities using Hibernate in the order of the list of Pks that is provided to the Hibernate query?
In the code below, the order of the list output is in ascending order rather than the order in which the Pks is supplied in the argument
Criteria criteria = s.createCriteria(entityClass).add(Restrictions.in(idPropertyName, pks));
List list = criteria.list();
You get them, then sort them using a comparator that compares the index of each entity in the list.
For example:
Map<Long, Integer> indexById = new HashMap<>();
for (int i = 0; i < pks.size(); i++) {
indexById.put(pks.get(i), i);
}
List<MyEntity> entities = seachByIds(pks);
entities.sort(Comparator.comparing(entity -> indexById.get(entity.getId())));
As I explained in this article, there are several ways you can achieve this goal.
In your example, you were using the legacy Hibernate Criteria, but since it's been deprecated since Hibernate 4 and will probably be removed in Hibernate 6.
Therefore, it's better to use one of the following alternatives.
Note that, in your example, you have the entity identifier values defined in a pks variable of the List type, and I'm going to reuse that in the examples below as well.
JPQL
You can use a JPQL query like the following one:
List<Book> books = entityManager
.createQuery(
"select b " +
"from Book b " +
"where b.id in (:ids)", Book.class)
.setParameter("ids", pks)
.getResultList();
When using JPQL, The ids parameter will pass the entity identifiers in the same order they were defined in the pks variable.
Criteria API
If you want to build the query dynamically, then you can use a Criteria API query:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Book> query = builder.createQuery(Book.class);
ParameterExpression<List> ids = builder.parameter(List.class);
Root<Book> root = query
.from(Book.class);
query
.where(
root.get("id").in(
ids
)
);
List<Book> books = entityManager
.createQuery(query)
.setParameter(ids, pks)
.getResultList();
When using Criteria API, The ids parameter will pass the entity identifiers in the same order they were defined in the pks variable.
Hibernate-specific multiLoad
List<Book> books = entityManager
.unwrap(Session.class)
.byMultipleIds(Book.class)
.multiLoad(pks);
By default, the Hibernate multiLoad, The ids parameter will pass the entity identifiers in the same order they were defined in the pks variable. Only if you called enableOrderedReturn(false) explicitly, then the result set will not be ordered.
Now, the JPQL and Criteria API can benefit from the hibernate.query.in_clause_parameter_padding optimization as well, which allows you to increase the SQL statement caching mechanism.
For more details about loading multiple entities by their identifier, check out this article.

Spring framework data JPA Inner Join on multiple columns

I would like to do the following query using spring jpa. I am able to build the where clause for my statement with Predicate.toPredicate. However, I don't know how to join on more than one column. On a single column it can be done in the repository using #Query and #Param
SELECT a.name, a.column_x, b.column_y
FROM table_a a
INNER JOIN table_b b
ON b.name = a.name
AND b.pk_2 = a.pk_2
AND b.pk_3 = a.pk_3
WHERE ...;
Another question I have is, is an intermediate tableA_tableB association beneficial if I have something like this, oneToMany relations.
Table 1: thing
thing_name
type
tenant
other1
other2
Table 2: thing_sub_prop
prop_name
value
Association table: thing_thing_sub_prop
type
thing_name
tenant
prop_name
value
Or is it better to just have two tables, thing and thing_sub_prop with the primary key columns of thing repeated in thing_sub_prop as a foreign key?

How to bulk delete from element collection in jpa

I'm using jpa 2.0 and I have the following entity:
#Entity
public class Folder{
#ElementCollection
#CollectionTable(name="folder_files")
private Set<String> files;
// .....
}
Given a file name, I would like to delete all entries where files == theGivenFileName. In sql it would be something like this:
Delete from folder_files where files = XXX
Is there a way to perform this query using criteria-api?
If not, is there a way to perform this query using jpql?
UPDATE:
I think my question was not clear enough:
Since jpql uses entities (and not tables) I cannot just perform the sql written above plus since I'm using #ElementCollection I don't know how to address this variablr or even deal with it. I would like to delete all entries in that collection (in my case, the files set) which holds a given value, from all entities. Is that possible using jpql or (even better) criteria-api?
The Delete FROM clause requires an Entity, so there is no way to delete from an element collection from what I understand.
You can use a native SQL query, or you can map the element collection as a OneToMany to an Entity instead.
You can use the like query just the syntax is slightly changed.
query = em.createQuery("SELECT i FROM Item i WHERE UPPER(i.name) LIKE :keyword ");
query.setParameter("keyword", "%" + keyword.toUpperCase() + "%");
You can read more on following link,
https://forums.oracle.com/forums/thread.jspa?threadID=423742
Updated:
#Noam you can do it: Like in Criteria API
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.between("weight", minWeight, maxWeight) )
.list();
Kindly read more on it at following link:
http://ctpconsulting.github.com/query/1.0.0.Alpha3/criteria.html
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html
This cannot be done. Via JPQL it does not work because DELETE statement can only be applied to entities. Excerpt from JPA 2.0 specification:
Bulk update and delete operations apply to entities of a single entity
class (together with its subclasses,if any).
...
delete_statement ::= delete_clause [where_clause]
delete_clause ::= DELETE FROM entity_name [[AS] identification_variable]
Also it doesn't work via Criteria API. CriteriaQuery supports only selecting - not updates or removals.
You have to go for native SQL.

Categories