Issue
Currently we have two endpoints in our API :
- One to update one entity
- An various ones to update one field of a Collection of entity
The first one only use saveOrUpdate method of hibernate
While the second one create a custom HQL query to update the desired field.
I would like to make only one endpoint. The idea would be receiving a payload representing the entity. Each field of the entity that are not null would be field that we should update.
I wanted to do that in this way, but it doesn't work as setParameter could set parameters that are not in the String. Any ideas ?
public long update(Collection<Long> toUpdate, SaleItemDTO newValues) {
if (toUpdate.size() == 0) return 0;
StringBuilder hql = new StringBuilder("UPDATE SaleItem SET ");
if (!newValues.getName().isEmpty()) hql.append("name = :name,");
if (newValues.getPrice() != null) hql.append("price = :price,");
if (newValues.getTag() != null) hql.append("tag = :tag,");
if (newValues.getCategory() != null) hql.append("category.id = :categoryId,");
if (newValues.isRecurringSale() != null) hql.append("isRecurringSale = :isRecurringSale,");
if (newValues.isCallProduct() != null) hql.append("callProduct = :callProduct,");
hql.deleteCharAt(hql.length() - 1).append(" WHERE id in :ids");
return this.sessionFactory
.getCurrentSession()
.createQuery(hql.toString())
.setParameter("name", newValues.getName())
.setParameter("price", newValues.getPrice())
.setParameter("tag", newValues.getTag())
.setParameter("categoryId", newValues.getCategory().getId())
.setParameter("isRecurringSale", newValues.isRecurringSale())
.setParameter("callProduct", newValues.isCallProduct())
.setParameter("ids", toUpdate)
.executeUpdate();
}
Solution
Okay, fix it with Criteria API
public long update(Collection<Long> toUpdate, SaleItemDTO newValues) {
if (toUpdate.size() == 0) return 0;
CriteriaBuilder criteriaBuilder = this.sessionFactory.getCriteriaBuilder();
// create update
CriteriaUpdate<SaleItem> update = criteriaBuilder.createCriteriaUpdate(SaleItem.class);
// set the root class
Root<SaleItem> saleItemRoot = update.from(SaleItem.class);
// set update and where clause
if (!newValues.getName().isEmpty()) update.set("name", newValues.getName());
if (newValues.getPrice() != null) update.set("price", newValues.getPrice());
//if (newValues.getCategory() != null) update.set("category.id", newValues.getCategory().getId());
if (newValues.getTag() != null) update.set("tag", newValues.getTag());
if (newValues.isRecurringSale() != null) update.set("isRecurringSale", newValues.isRecurringSale());
if (newValues.isCallProduct() != null) update.set("callProduct", newValues.getProduct());
update.where(saleItemRoot.get("id").in(toUpdate));
return this.sessionFactory.getCurrentSession().createQuery(update).executeUpdate();
}
Answered By - Paul Serre
Answer Checked By - Pedro (JavaFixing Volunteer)