How to update an object with another object value in JPQL using Spring JPA - spring

I'm facing a problem in JPQL. I have two entities like below
class Employee{
private Long id;
private String name;
private Department department;
public void setId(Long id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
public void setDepartment(Department department){
this.department = department
}
public Long getId(){
return this.id;
}
public String getName(){
return this.name;
}
public Department getDepartment(){
return this.department;
}
}
and...
class Department{
private Long id;
private String name;
public void setId(Long id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
public Long getId(){
return id;
}
public String getName(){
return name;
}
}
Now i need to update an Employee's department. I have tried the query below.
update Employee e set e.department.id = 'XXX' where e.id in (?1);
This is giving exception like
java.lang.IllegalStateException: org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations.
Can you please guide me, How can i solve this issue?
Cheers,
Teja.

In your Spring Data JPA repository interface do:
interface EmployeeRepository extends Repository<Employee, Long> {
#Modifying
#Transactional
#Query("update Employee e set e.department = ?2 where e = ?1")
void updateDepartment(Employee employee, Department department);
}
Be sure to realize:
If you're executing modifying queries, you're bypassing lifecycle callbacks on the entities. This is a fundamental characteristic of JPA.
If you need lifecycle callbacks applied, load the Employee, manually set the Department, store the Employee.

#Modifying(clearAutomatically = true)
#Transactional
#Query("update Employee e set e.department = ?2 where e = ?1")
void updateDepartment(Employee employee, Department department);
#Modifying will separate it from select queries.
#Transactional will help transaction with the database.
#Query is the same old query execution.

Related

Spring boot does not editing record in to mysql

when i updating the records via postman record not updating it will create a new record i don't know why.i attached screenshot below along with code what i tried so far.i have attched the controller,service,
entity,repository.
i am tring this since yesterday problem not solved please some one will help me to solve
enter image description here
EmployeeController
#PutMapping("/edit/{id}")
private Employee update(#RequestBody Employee employees,#PathVariable(name = "id") long id)
{
Employee emp = services.get(id);
services.saveOrUpdate(emp);
return employees;
}
Services
//updating a record
//updating a record
public void update(Employee employees, int id)
{
repo.save(employees);
}
Repository
#Repository
public interface EmployeeRepository extends CrudRepository<Employee,Long> {
}
Entity
#Entity
#Table(name="Records")
public class Employee {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="fname")
private String fname;
#Column(name="lname")
private String lname;
#Column(name="city")
private String city;
#Column(name="phone")
private String phone;
#Column(name="salary")
private String salary;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
}
This an example of UPDATE and it worked for me.
//HTTP PUT
#PutMapping("/owners/{id}")
public void updateOwner(#RequestBody Owner owner, #PathVariable int id) {
owner.setId(id);
ownerRepos.save(owner);
}
I used the CrudRepository too.
Also I notice that you call services.saveOrUpdate(emp) but at the same time you showed us "public void update(Employee employees, int id)" below. If'd better if you could show the definition of the method saveOrUpdate()
SaveOrUpdate uses the ID of the object to determine if the object is the same or new. When updating, you're not considering the ID of the employee. You should first fetch the Object from DB and update the same object. The updates should take place on a persistent object

Getting null values with data in list of collection of object

I am trying to add few employee objects inside the list named collectionofEmployees here.I am able to add the data but i am getting first record for custom object attributes as nulls.The data is getting inserted after that properly.
Here is my controller.
#RestController
public class CustomController {
#Autowired
Employees collectionofEmployees;
#RequestMapping("/add")
public Employees add() {
collectionofEmployees.add(new Employee(1,"XYZ"));
collectionofEmployees.add(new Employee(3, "VTY"));
return collectionofEmployees;
}
Here is my Employees Model class which contains list of employee
#Component
public class Employees {
#Autowired
private List<Employee>employees;
public List<Employee> getEmployees() {
return employees;
}
public Employees(List<Employee> employees) {
super();
this.employees = employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public void add(Employee employee)
{
this.employees.add(employee);
}
Here is my employee class
#Component
public class Employee {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public Employee() {
super();
}
public Employee(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
The output i am getting is as {"employees":[{"id":null,"name":null},{"id":1,"name":"XYZ"},{"id":3,"name":"VTY"}]}
Help would be appreciated alot:)I want to avoid nulls
Try to remove #Component from Employee class. It is initialized by Spring and injected to your
#Autowired
private List<Employee>employees
As i still dont know how to avoid nulls at time of intialisation done by spring,for temporary purpose i have added collectionofEmployees.getEmployees().remove(0) under add method which removes the nulls from the input.

Hibernate HQL doesn`t recognize "OUTER APPLY" as a keyword [duplicate]

I need to use raw SQL within a Spring Data Repository, is this possible? Everything I see around #Query is always entity based.
The #Query annotation allows to execute native queries by setting the nativeQuery flag to true.
Quote from Spring Data JPA reference docs.
Also, see this section on how to do it with a named native query.
YES, You can do this in bellow ways:
1. By CrudRepository (Projection)
Spring Data Repositories usually return the domain model when using query methods. However, sometimes, you may need to alter the view of that model for various reasons.
Suppose your entity is like this :
import javax.persistence.*;
import java.math.BigDecimal;
#Entity
#Table(name = "USER_INFO_TEST")
public class UserInfoTest {
private int id;
private String name;
private String rollNo;
public UserInfoTest() {
}
public UserInfoTest(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", nullable = false, precision = 0)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "name", nullable = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Basic
#Column(name = "roll_no", nullable = true)
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
Now your Projection class is like below. It can those fields that you needed.
public interface IUserProjection {
int getId();
String getName();
String getRollNo();
}
And Your Data Access Object(Dao) is like bellow :
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.ArrayList;
public interface UserInfoTestDao extends CrudRepository<UserInfoTest,Integer> {
#Query(value = "select id,name,roll_no from USER_INFO_TEST where rollNo = ?1", nativeQuery = true)
ArrayList<IUserProjection> findUserUsingRollNo(String rollNo);
}
Now ArrayList<IUserProjection> findUserUsingRollNo(String rollNo) will give you the list of user.
2. Using EntityManager
Suppose your query is "select id,name from users where roll_no = 1001".
Here query will return an object with id and name column. Your Response class is like bellow:
Your Response class is like this:
public class UserObject{
int id;
String name;
String rollNo;
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
here UserObject constructor will get an Object Array and set data with the object.
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
Your query executing function is like bellow :
public UserObject getUserByRoll(EntityManager entityManager,String rollNo) {
String queryStr = "select id,name from users where roll_no = ?1";
try {
Query query = entityManager.createNativeQuery(queryStr);
query.setParameter(1, rollNo);
return new UserObject((Object[]) query.getSingleResult());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
Here you have to import bellow packages:
import javax.persistence.Query;
import javax.persistence.EntityManager;
Now your main class, you have to call this function. First get EntityManager and call this getUserByRoll(EntityManager entityManager,String rollNo) function. The calling procedure is given below:
Here is the Imports
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
get EntityManager from this way:
#PersistenceContext
private EntityManager entityManager;
UserObject userObject = getUserByRoll(entityManager,"1001");
Now you have data in this userObject.
Note:
query.getSingleResult() return a object array. You have to maintain the column position and data type with the query column position.
select id,name from users where roll_no = 1001
query return a array and it's [0] --> id and [1] -> name.
More info visit this thread and this Thread
Thanks :)
It is possible to use raw query within a Spring Repository.
#Query(value = "SELECT A.IS_MUTUAL_AID FROM planex AS A
INNER JOIN planex_rel AS B ON A.PLANEX_ID=B.PLANEX_ID
WHERE B.GOOD_ID = :goodId",nativeQuery = true)
Boolean mutualAidFlag(#Param("goodId")Integer goodId);
we can use createNativeQuery("Here Native SQL Query ");
for Example :
Query q = em.createNativeQuery("SELECT a.firstname, a.lastname FROM Author a");
List<Object[]> authors = q.getResultList();
This is how you can use in simple form
#RestController
public class PlaceAPIController {
#Autowired
private EntityManager entityManager;
#RequestMapping(value = "/api/places", method = RequestMethod.GET)
public List<Place> getPlaces() {
List<Place> results = entityManager.createNativeQuery("SELECT * FROM places p limit 10").getResultList();
return results;
}
}
It is also possible to use Spring Data JDBC, which is a fully supported Spring project built on top of Spring Data Commons to access to databases with raw SQL, without using JPA.
It is less powerful than Spring Data JPA, but if you want lightweight solution for simple projects without using a an ORM like Hibernate, that a solution worth to try.

I've a field which is not primary key id. how can i fetch data using JPA repository through that non primary key?

I've a model User. There's a field which is contact and it's a non primary key. How can i fetch data using this key? it's an unique key.
This is my model.
#Entity
#Table(name = "tbl_user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
long userId;
#Column(name = "name")
String name;
#Column(name = "email")
String email;
#Column(name = "contact")
String contact;
#Column(name = "category")
String category;
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public User() {
}
}
This is the method inside Service layer.
public User getUserByContact(String contact) {
Optional<User> result = userRepository.findByContact(contact);
User user = result.get();
return user;
}
This is the repository.
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.contact = ?1")
User findByContact(String contact);
}
I'm getting an error on "select u from User u where u.contact = ?1" this portion under User and it's saying "cant resolve symbol User". Would appreciate any sort of help.
Leave out the #Query part, that part is not needed if you extend a JpaRepository. As stated in the documentation JPA derives the query from the method name.
I'm not sure whether this is an issue, but in your entity class you use a long for id and in your repository definition (JpaRepository<User, Long>) you use a Long. Correct me if this is not problematic.
If you want to use #Query, then the right approach would be to use #Param to define the variable
#Query("select u from User u where u.contact = :contactVar ", nativeQuery = true)
User findByContact(#Param("contactVar")String contactVar);

Spring JPARepository querying many to many intersection table

I have 3 entity classes as follows (Example taken from https://hellokoding.com/jpa-many-to-many-extra-columns-relationship-mapping-example-with-spring-boot-maven-and-mysql/)
Book class
#Entity
public class Book{
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Book() {
}
public Book(String name) {
this.name = name;
bookPublishers = new HashSet<>();
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
Publisher class
#Entity
public class Publisher {
private int id;
private String name;
private Set<BookPublisher> bookPublishers;
public Publisher(){
}
public Publisher(String name){
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(mappedBy = "publisher")
public Set<BookPublisher> getBookPublishers() {
return bookPublishers;
}
public void setBookPublishers(Set<BookPublisher> bookPublishers) {
this.bookPublishers = bookPublishers;
}
}
Intersection Table
#Entity
#Table(name = "book_publisher")
public class BookPublisher implements Serializable{
private Book book;
private Publisher publisher;
private Date publishedDate;
#Id
#ManyToOne
#JoinColumn(name = "book_id")
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
#Id
#ManyToOne
#JoinColumn(name = "publisher_id")
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
#Column(name = "published_date")
public Date getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(Date publishedDate) {
this.publishedDate = publishedDate;
}
}
I want to query 2 things,
Get list of books belonging to a particular publisher e.g. get all books associated with publisher 100
Get list of books not associated with a particular publisher e.g. get all books not associated with publisher 100
I want to achieve this using a simple JPARepository query if possible like findByXYZIn(...) etc.
Please let me know if querying a many to many relation is possible using JPA repository queries and if yes, whether I can do it directly or would it require any changes in the entity classes
In BookRepository
Get publisher's books
findBooksByBookPublishersPublisherId(Long publisherId)
Get books not published by publisher
findBooksByBookPublishersPublisherIdNot(Long publisherId)
IMHO Publication is much more apropriate name then BookPublisher in your case as Publisher by itself could be BookPublisher (a published that publishing books)
I'm not sure if you can make it just by method name. But you definitely can use JPA query. Something like this: "SELECT b FROM Book b JOIN b.bookPublishers bp JOIN bp.publisher p WHERE p.id = ?1". and with not equal for the second case
Well you can use named Queries to fulfill your requirements:
#Query("select b from Book b where b.publisher.idd = ?1")
Book findByPublisherId(int id);
#Query("select b from Book b where b.publisher.idd <> ?1")
Book findByDifferentPublisherId(int id);
Take a look at Using #Query Spring docs for further details.

Resources