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
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");
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));
}
}
}
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.
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();
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)");