How to get count of updated records in spring data jpa? - spring

I am using spring data jpa with hibernate as jpa persistence provider.
I am using native queries in my application. There are some update queries and I would like to get the actual number of records updated when the update query gets executed. Is there a way in spring data jpa to do this?
I am currently following the below approach;
#Modifying
#Query(value="update table x set x_provision = ?1 where x_id = ?2", nativeQuery=true)
int updateProvision(Integer provision, Integer id);
#Transactional is added on service layer.
The problem here is that when the table gets updated I get the count as 1. But there are some cases where no rows are updated. In this case also I get the count as 1. But I would like to receive the actual number of records updated which sometimes is 0.
Can someone let me know if I am doing something wrong here?

If you take a look at ModifyingExecutor, which is used to execute this query
#Override
protected Object doExecute(AbstractJpaQuery query, Object[] values) {
int result = query.createQuery(values).executeUpdate();
if (em != null) {
em.clear();
}
return result;
}
Then you see, it only delegates to native JPA infrastructure, to return number of updated elements.
So, this might have to do with used database or ORM framework configuration, other than that, the query you wrote should return correct result.

Related

How can I write a custom query with spring in mongo?

I'm trying to make a query and fetch data over mongodb with Spring. But I don't know mongo and spring very well. I have these fields in my table. How can I write a custom query with this query in SQL? I mean give the qp value of the record whose id is this. How can I write this please help..
SELECT qp
FROM tableName
WHERE id = request.getId();
my custom query method is it true?
public Object findQueryParams(ProcessInfo processInfo ){
Query query = Query.query(Criteria.where("id").is(processInfo .getId()).is(processInfo .getQueryParams()));
return query;
}

How to fetch multiple entities by a list of natural ids with Hiberate or JPA repository?

If I have a list of natural Ids, how can I fetch all the records in the DB associated with these natural Ids at once?
All I've seen are methods that let you find an entity by a natural Id, an example of one is shown below.
#Override
public Optional<T> findBySimpleNaturalId(ID naturalId) {
Optional<T> entity = entityManager.unwrap(Session.class)
.bySimpleNaturalId(this.getDomainClass())
.loadOptional(naturalId);
return entity;
}
I am looking for a method that can take a list natural Ids and fetch all the entities with these natural Ids. My current Entity has a autogenerated UUID and a naturalId and I'd like to keep it this way.
Is there something like this below
List<Song> songs = entityManager
.unwrap(Session.class)
.byMultipleSimpleNaturalIds(Song.class)
.multiLoad(songGroup.getSongIds());
// or using the repository
customRepository.findAllByNaturalId(...)
The examples you've seen are showing you how to build them yourself, as spring does not provide individual methods for you; it knows nothing about properties in your entity other than it must have an id. If you want a findAllByNaturalId method, you have to define it in the interface.
Specifying this in your customRepository:
public List<Song> findByNaturalIdIn(List<Int> naturalIds);
Spring should generate an implementation that creates a query similar to "Select s from Song s where s.naturalId In :naturalIds".
If it doesn't, just add that JPQL query string as an annotation and it will execute it for you:
#Query(value = "Select s from Song s where s.naturalId In :naturalIds")
public List<Song> findByNaturalIdIn(List<Int> naturalIds);
Or you can write your own implementation method to execute your loadOptional calls, or any query you wish, but you still must define the method in your repository.

SpringData JPA: Query with collection of entity as parameter

I have a list of entities on which I want to perform an update, I know I could update the table with list of String/Integer.. etc as the parameter with something like
#Query("update tableName i set i.isUpdated = true where i.id in :ids")
void markAsUpdated(#Param("ids") List<Integer> itemIds);
I'm trying to avoid repeated conversion of list of entities to list of Ids for making the query in DB. I know there are deleteAll and deleteInBatch commands which accept parameter as list of entities.
How do I do this in JPA Query, I tried the following but it didn't work yet.
#Modifying(flushAutomatically = true, clearAutomatically = true)
#Query("update tableName i set i.updated = true where i in :items")
void markAsUpdated(#Param("items") List<Item> items)
The query needs ids, it doesn't know how to deal with entities.
You have multiple options:
Just pass ids to the method, the client is responsible for extracting ids.
Pass entities and use SpEL for extracting ids
As suggested in the comments use a default method to offer both APIs and to delegate from one to the other.
As for the question that came up in the comments: You can move the method for extracting the id into a single method by either have relevant entities implement an interface similar to this one:
interface WithId {
Long getId();
}
Or by passing a lambda to the method, doing the conversion for a single entity:
List<ID> extractIds(List<E> entities, Function<E, ID> extractor) {
// ...
}

How to Return all instances of the type with the given ID in JPA SpringBoot?

I'm trying to return (or fetch) all the records from the database based on an ID provided by me. I'm using JPA and i'm aware of findAll() method but it returns all the records without any criteria, I created a custom query and it is only returning a unique value from the table but i want to return all records based on a criteria.
For example, findAllByUserID(String UserID) method should return all the records based on that UserID not just one.
I'd appreciate any help or suggestion.
Thanks
Have a look at the doc. There you will find the keywords you can use to declare methods in repository interfaces that will generate the according queries:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
In your case: If userID is an attribute of your entity you can add a method
List<YourEntity> findByfindAllByUserID(String userId)
to your repository interface.
First, make sure that you're not using any aggregate function in your select query such as DISTINCT()
Then make sure that the the method which is implementing that query is returning a List of you're desired result.
here's how it should look :
#Query("select t from table t where t.code = ?1")
List<Result> findAllByUserID(String UserID);

Retrieving selected fields from database using Hibernate

I'm retrieving a list of rows with selected fields from Oracle database using Hibernate. The retrieval is made by the following method in one of the DAOs in my application.
#SuppressWarnings("unchecked")
public List<Object[]> getOldFileName(String []ids)
{
int len=ids.length;
Long longType[]=new Long[len];
for(int i=0;i<len;i++)
{
longType[i]=Long.valueOf(ids[i]);
}
return sessionFactory.getCurrentSession().createQuery("select catId, catImage from Category where catId in(:id)").setParameterList("id", longType).list();
}
Here I'm fetching two fields categoryId and categoryImage as listed in the given HQL query based on the catId supplied as an array of String[] as a method parameter via Spring. It works fine and there is no question about it.
But regarding my requirements, retrieving catId again is completely unnecessary and I would like to remove catId from the list of fields in the query something simply like the following.
select catImage from Category where catId in(:id)
If I try to execute this query then the following call to the preceding method inside the Spring controller class,
String temp[]=request.getParameter("setDel").split(",");
List<Object[]> oldFileNames = categoryService.getOldFileName(temp);
//Invokes the preceding method in DAO.
causes the following exception to be thrown,
java.lang.ClassCastException: java.lang.String cannot be cast to
[Ljava.lang.Object;
The exception message indicates that java.lang.String cannot be cast to an array of Objects - Object[]. It appears that the HQL statement attempts to get only a single value of type String instead of retrieving List<Object[]>.
I just want to delete files which are stored in a directory after retrieving their names from the database and mentioning of catId in the list of fields in HQL is completely unnecessary.
Why do I need to add catId in the list of fields of the HQL statement in this scenario?
The return type for the list should be List. When only one column comes back hibernate does not put the result into and Object[]

Resources