Update a column using hibernate - java

I have two classes Employee and Department.
public class Employee {
int empId;
String empName;
Boolean isEmpAvailable;
String empAddress;
Department department;
}
public class Department {
int deptId;
String deptName;
}
I have created hibernate files files for both classes Department.hbm.xml and Employee.hbm.xml
I like to update the column isEmpAvailable in the table Employee basing on a deptid in Department table.
Here I am facing problem with update query which I am not clear after reading in online documentation
public void updateEmployee(Employee emp, Department deptid){
String query= " update Employee set isEmpAvailable=? where deptid=?
Object[] values= {"true","133"};
getHibernateTemplate.update(query,values);
}
When i run the code the column doesn't get update. A error is thrown as
Entity not recognized: update Employee set isEmpAvailable=? where deptid=?
I have read online docs which have methods of getHibernateTemplate() which have return type as integer. Here I like to update the database directy by calling dao.updateEmployee without any returntype. I am unable do it. Please suggest me

Update in hibernate is done this way :
String hqlUpdate =
"update Employee e " +
"set e.isEmpAvailable = :isEmpAvailable " +
"where e.deptid = :deptid";
int updatedEntities = session.createQuery( hqlUpdate )
.setBoolean( "isEmpAvailable", isEmpAvailable )
.setInt( "deptid", deptid )
.executeUpdate();
OR
String jpqlUpdate =
"update Employee e " +
"set e.isEmpAvailable = :isEmpAvailable " +
"where e.deptid = :deptid";
int updatedEntities = entityManager.createQuery( jpqlUpdate )
.setBoolean( "isEmpAvailable", isEmpAvailable )
.setInt( "deptid", deptid )
.executeUpdate();
OR
String hqlVersionedUpdate =
"update versioned Employee e " +
"set e.isEmpAvailable = :isEmpAvailable " +
"where e.deptid = :deptid";
int updatedEntities = s.createQuery( hqlUpdate )
.setBoolean( "isEmpAvailable", isEmpAvailable )
.setInt( "deptid", deptid )
.executeUpdate();

If you want you can also use the saveOrUpdate() function. In this link there is an example and some documentation.

Related

Hibernate insert doesn't work with custom native query

In a spring boot project and database SQL Server, I'm doing some inserts where I need to return the id of the record
I have a Entity with few fields:
public class PackGroupEntity{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long group_id;
private String group;
private String remark;
private String description;
....
}
I simplified the insert just to ask the question.
I have an insert statement and I need to retrieve the id from the inserted record.
String query = String.format(
"insert into pack_group(group, remark, description ) " +
"values ( %s, %s, %s)", "a","b","c" );
Query q = entityManager.createNativeQuery(query );
BigInteger biid = (BigInteger) q.getSingleResult();
long id = biid.longValue();
And I get this error
com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.
Based on this answer here that I can use returning id so I tried but:
String query = String.format(
"insert into pack_group(group, remark, description ) " +
"values ( %s, %s, %s ) returning group_id;", "a","b","c" );
Query q = entityManager.createNativeQuery(query );
BigInteger biid = (BigInteger) q.getSingleResult();
long id = biid.longValue();
but it throws an error
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near 'returning'.
Can someone help me, please?
This things is SQL Server does not support returning syntax.
If you want get id for inserted row - you should use keyword output
This is official docs for using output with INSERT statement:
https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-ver15#a-using-output-into-with-a-simple-insert-statement
You can also see this answer with examples for different SQL Server version for C# (but query does not different for Java):
https://stackoverflow.com/a/18373524/16644196
SQLServer doesn't support the returning clause. Instead, use the output clause.
String query = String.format("INSERT INTO pack_group(group, remark, description) "
+ "OUTPUT INSERTED.group_id "
+ "VALUES( %s, %s, %s )", "a","b","c");

MySql - One to Many Join, mapping JOIN with JDBI to List

I'm trying to write an object query with JDBI that will grab one complete row from the left table and join all matching rows in the right table as a List (one author can have many books).
Author
id, name, createdAt, updatedAt, email, phoneNumber
Book
id, title, authorId, categories, createdAt, updatedAt
The eventual object I want to create is structured as follows:
class AuthorWithBooks() {
int id,
String name,
List<String> categories,
long createdAt,
long updatedAt,
String email,
String phoneNumber
List<Book> books
}
where book is:
class Book {
id,
title,
authorId,
categories,
createdAt,
updatedAt
}
Here is the query I'm trying (doesn't grab the Books as List as is)
#SqlQuery("SELECT " + AUTHOR_COLUMN MAMES + ", " + BOOK_COLUMN_NAMES + " FROM authors as author" +
" LEFT JOIN books AS book" +
" ON author.id = book.authorId" +
" WHERE id = :authorId")
List<AuthorWithBooks> getAuthorWithBooks(#Bind("authorId") int authorId);
Would appreciate any help/someone pointing me in the right direction!
Thanks!
It seems like you need #UseRowReducer
The implementation for your example would look something like this:
#SqlQuery("SELECT a." + AUTHOR_COLUMN MAMES + ", b." + BOOK_COLUMN_NAMES + " FROM authors as author" +
" LEFT JOIN books AS book" +
" ON author.id = book.authorId" +
" WHERE id = :authorId")
#RegisterBeanMapper(value = Book.class, prefix = "b")
#RegisterBeanMapper(value = AuthorWithBooks.class, prefix = "a")
#UseRowReducer(AuthorBookReducer.class)
List<AuthorWithBooks> getAuthorWithBooks(#Bind("authorId") int authorId);
class AuthorBookReducer implements LinkedHashMapRowReducer<Integer, Author> {
#Override
public void accumulate(Map<Integer, Author> map, RowView rowView) {
Author author = map.computeIfAbsent(rowView.getColumn("a_id", Integer.class),
id -> rowView.getRow(Author.class));
if (rowView.getColumn("b_id", Integer.class) != null) {
author.getBooks().add(rowView.getRow(Book.class));
}
}
}

Check if row record exists with JPA

I want to check if row record by id exists. I tried this:
public Optional<PaymentTransactions> transactionByUnique_Id( String unique_id ) throws Exception
{
String hql = "select e from " + PaymentTransactions.class.getName() + " e where e.unique_id = :unique_id";
TypedQuery<PaymentTransactions> query = entityManager.createQuery( hql, PaymentTransactions.class ) .setParameter( "unique_id", unique_id );
Optional<PaymentTransactions> paymentTransaction = query.getResultList().stream().findFirst();
return paymentTransaction;
}
Optional<PaymentTransactions> tnx = transactionsService.transactionByUnique_Id( transaction.getTransactionId() );
if(tnx.isPresent())
{
return "test";
// This method should be called only when DB record exists
}
But I alway get present object. What is the proper way to implement this check.

How to map Results when Querying raw SQL using Ebean

Using Postgres Tables created by Ebean, I would like to query these tables with a hand-written statement:
SELECT r.name,
r.value,
p.name as param1,
a.name as att1,
p2.name as param2,
a2.name as att2
FROM compatibility c
JOIN attribute a ON c.att1_id = a.id
JOIN attribute a2 ON c.att2_id = a2.id
JOIN PARAMETER p ON a.parameter_id = p.id
JOIN PARAMETER p2 ON a2.parameter_id = p2.id
JOIN rating r ON c.rating_id = r.id
WHERE p.problem_id = %d
OR p2.problem_id = %d
Each of the joined tables represent one of my model classes.
The query executes fine, but I don't know how I would proceed:
How do I even execute the query using Play 2.2. and Ebean?
How can I map this query to an iterable object? Do I need to create a Model class which contains all the fields from the query, or can I use some sort of HashMap?
How can I parameterize the query in a safe way?
To execute this query you need to use RawSql class. You will also have to create class to which results will be casted.
Here is a code of exemplary result class:
import javax.persistence.Entity;
import com.avaje.ebean.annotation.Sql;
#Entity
#Sql
public class Result {
String name;
Integer value;
String param1;
String param2;
String att1;
String att2;
}
And example of executing this query:
String sql
= " SELECT r.name,"
+ " r.value,"
+ " p.name as param1,"
+ " a.name as att1,"
+ " p2.name as param2,"
+ " a2.name as att2"
+ " FROM compatibility c"
+ " JOIN attribute a ON c.att1_id = a.id"
+ " JOIN attribute a2 ON c.att2_id = a2.id"
+ " JOIN PARAMETER p ON a.parameter_id = p.id"
+ " JOIN PARAMETER p2 ON a2.parameter_id = p2.id"
+ " JOIN rating r ON c.rating_id = r.id"
+ " WHERE p.problem_id = %d"
+ " OR p2.problem_id = %d"
RawSql rawSql =
RawSqlBuilder
.parse(sql)
.columnMapping("r.name", "name")
.columnMapping("r.value", "value")
.create();
Query<Result> query = Ebean.find(Result.class);
query.setRawSql(rawSql)
.where().gt("amount", 10);
List<Result> list = query.findList();

Query update using hibernate runs into QueryException : Unable to resolve path

I have following entities, and need to update a field that is in a specific field and its removedDate is null. But the following code returns exception.
#Entity
public class Cart implements Serializable {
#Id
#GeneratedValue
private Long id;
#OneToMany(cascade = CascadeType.ALL)
#LazyCollection(LazyCollectionOption.FALSE)
private List<CartItem> items;
public Cart() {
}
getters and setters
}
#Entity
public class CartItem {
#Id
#GeneratedValue
private long id;
#ManyToOne
private Product pro;
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date addedDate;
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date removedDate;
getters and setters
}
Hibernate Code 1
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE CartItem.id IN (Select Cart.items.id From Cart"
+ " WHERE Cart.id = :cartId"
+ " AND Cart.items.pro.id = :pro"
+ " AND Cart.items.removedDate is null)");
query.setParameter("currentDateTime", dt.getCurrentDateTime());
query.setParameter("cartId", cartId);
query.setParameter("pro", proId);
int result = query.executeUpdate();
Exception of Code 1
SEVERE: org.hibernate.QueryException: Unable to resolve path [CartItem.id], unexpected
token [CartItem] [UPDATE com.myproject.CartItem SET removedDate =
:currentDateTime WHERE CartItem.id IN (Select Cart.items.id From
com.myproject.Cart WHERE Cart.id = :cartId AND cart.items.pro.id = :proId
AND Cart.items.removedDate is null))]
at org.hibernate.hql.internal.ast.tree.IdentNode.resolveAsNakedComponentPropertyRefLHS(IdentNode.java:245)
at org.hibernate.hql.internal.ast.tree.IdentNode.resolve(IdentNode.java:110)
at org.hibernate.hql.internal.ast.tree.DotNode.resolveFirstChild(DotNode.java:177)
at org.hibernate.hql.internal.ast.HqlSqlWalker.lookupProperty(HqlSqlWalker.java:577)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.addrExpr(HqlSqlBaseWalker.java:4719)
Hibernate Code 2
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE id IN (Select items.id From Cart"
+ " WHERE id = :CartId"
+ " AND items.pro.id = :pro"
+ " AND items.removedDate is null)");
Exception of Code 2
SEVERE: org.hibernate.QueryException: illegal attempt to dereference collection
[{synthetic-alias}{non-qualified-property-ref}items] with element property
reference [id] [UPDATE com.myproject.CartItem SET removedDate =
:currentDateTime WHERE id IN (Select items.id From com.myproject.Cart WHERE
id = :cartId AND items.pro.id = :pro AND items.removedDate is null)]
at org.hibernate.hql.internal.ast.tree.DotNode$1.buildIllegalCollectionDereferenceException(DotNode.java:68)
at org.hibernate.hql.internal.ast.tree.DotNode.checkLhsIsNotCollection(DotNode.java:550)
at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:246)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:118)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:114)
Why don't you make your association bidirectional?
Add this to your CartItem entity:
#ManyToOne
private Cart cart;
Set the mappedBy on your cartItem fied in Cart:
#OneToMany(cascade = CascadeType.ALL, mappedBy="cart")
#LazyCollection(LazyCollectionOption.FALSE)
private List<CartItem> items;
The resulting HQL would be much simpler (and should work):
"UPDATE CartItem c SET c.removedDate = :currentDateTime "
+ " WHERE c.cart.id = :cartId"
+ " AND c.pro.id = :pro"
+ " AND c.removedDate is null"
Try this by adding an alias in the inner select query.
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE id IN (Select cart.items.id From Cart cart"
+ " WHERE cart.id = :CartId"
+ " AND cart.items.pro.id = :pro"
+ " AND cart.items.removedDate is null)");
EDIT 2
I did a bit of reading and found out that the object.collection.id works only for a 1:1 or an N:1 relation, not for a 1:N relation, which is what you have. Try this.
SELECT items.id
FROM Cart cart
LEFT JOIN cart.items items
WHERE cart.id = :CartId AND items.pro.id = :pro AND items.removedDate is null
Here is more info, info, info
Thanks to Hrishikesh's comment, I found the answer by providing the exact SQLQuery.
UPDATE cartItem SET removedDate = :currentDateTime"
+ " WHERE pro = :pro"
+ " AND removedDate IS NULL"
+ " AND id IN
( SELECT items_id from Cart_CartItem WHERE Cart_id = :CartId)
Try that:
Query query = session.createQuery("UPDATE CartItem SET removedDate = :currentDateTime "
+ " WHERE id IN (Select ci.id From Cart c inner join c.items ci"
+ " WHERE c.id = :cartId"
+ " AND ci.pro.id = :pro"
+ " AND ci.removedDate is null)");

Categories