How inject EntityManager to DAO or Servlet using JPA Hubernate - java

When I calling method onGet in Servlet I got NullPointerException. I checked it and method in DAO is correct implemented. Where should I inject entityManagaer object and how ? In DAO ? Or in Servlet ? I was trying do it with annotations but it doesn't work.
In method onGet I calling method getAllReservations() from ReservationDAO class and that method cause Nullpointerexception. I want retrieve data from my database. This method should return all data from dB what I want get. And how to fix it?
Database store two tables which contains two Reservation objects and two Person objects
My code below:
ReservationServlet class
package servlets;
import DAO.ReservationDAO;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import model.Reservation;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
#WebServlet("reservation")
public class ReservationServlet extends HttpServlet {
ReservationDAO reservationDAO = new ReservationDAO();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Reservation> reservationsList = reservationDAO.getAllReservations();
System.out.println("reservationsList size: " + reservationsList.size());
//String json = gson.toJson(reservationsList);
response.getWriter().write(reservationsList.get(0).getPerson().getName());
}
}
ReservationDAO class
package DAO;
import model.Reservation;
import javax.persistence.EntityManager;
import javax.persistence.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.util.List;
public class ReservationDAO {
#PersistenceUnit(unitName="restapi")
EntityManagerFactory emf = Persistence.createEntityManagerFactory("restapi");
#PersistenceContext(unitName="restapi")
EntityManager em;
#Transactional
public List<Reservation> getAllReservations() {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Reservation> criteriaQuery = builder.createQuery(Reservation.class);
Root<Reservation> employee = criteriaQuery.from(Reservation.class);
criteriaQuery.select(employee);
TypedQuery<Reservation> query = em.createQuery(criteriaQuery);
return query.getResultList();
}
public Reservation getReservationById(EntityManager em, int id) {
Query query = em.createQuery("FROM Reservation WHERE id =" + id);
return (Reservation) query.getSingleResult();
}
public void updateReservation(EntityManager em, int id, Reservation reservation) {
Query query = em.createQuery("UPDATE Reservation SET table_number = :tn, start_time = :st, end_time = :et WHERE id = :id");
query.setParameter("tn", reservation.getTableNumber()).setParameter("st", reservation.getStartTime())
.setParameter("et", reservation.getEndTime()).setParameter("id", reservation.getId()).executeUpdate();
}
public void removeReservation(EntityManager em, int id) {
Query query = em.createQuery("DELETE FROM Reservation WHERE id = :id");
query.setParameter("id", id).executeUpdate();
}
public void createReservation(EntityManager em, Reservation reservation) {
em.persist(reservation);
}
}
Reservation model class
package model;
import javax.persistence.*;
#Entity
public class Reservation {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "table_number", columnDefinition = "VARCHAR(30) NOT NULL")
private int tableNumber;
#Column(name = "start_time" ,columnDefinition = "VARCHAR(20) NOT NULL")
private String startTime;
#Column(name = "end_time", columnDefinition = "VARCHAR(20) NOT NULL")
private String endTime;
#ManyToOne
private Person person;
public Reservation() {
}
public Reservation(int tableNumber, String startTime, String endTime, Person person) {
this.tableNumber = tableNumber;
this.startTime = startTime;
this.endTime = endTime;
this.person = person;
}
public int getTableNumber() {
return tableNumber;
}
public void setTableNumber(int tableNumber) {
this.tableNumber = tableNumber;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public long getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void setId(long id) {
this.id = id;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Person model class
package model;
import javax.persistence.*;
import java.util.Collection;
import java.util.List;
import java.util.Set;
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "full_name")
private String name;
#Column(name = "phone_number")
private String phoneNumber;
private String email;
#OneToMany(mappedBy = "person")
private List<Reservation> reservationList;
public Person() {
}
public Person(String name, String phoneNumber, String email, List<Reservation> reservationList) {
this.name = name;
this.phoneNumber = phoneNumber;
this.email = email;
this.reservationList = reservationList;
}
public long 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 getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Reservation> getReservationList() {
return reservationList;
}
public void setReservationList(List<Reservation> reservationList) {
this.reservationList = reservationList;
}
}
App class - what I use to run application by Hibernate
import DAO.ReservationDAO;
import model.Person;
import model.Reservation;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.ArrayList;
import java.util.List;
public class App {
public void populateDb(EntityManager em) {
EntityTransaction transaction = em.getTransaction();
List<Reservation> reservationList = new ArrayList<>();
Person person1 = new Person("John Smith", "458-321-842", "sgfhvdsg#gmail.com", reservationList);
Reservation reservation1 = new Reservation(37, "12.37", "13.45", person1);
reservationList.add(reservation1);
Person person2 = new Person("Gonzalez", "123-456-789", "dsafi#gmail.com", reservationList);
Reservation reservation2 = new Reservation(24, "14.23", "16.22", person2);
reservationList.add(reservation2);
transaction.begin();
em.persist(person1);
em.persist(reservation1);
em.persist(person2);
em.persist(reservation2);
transaction.commit();
}
public static void main(String[] args) {
App app = new App();
EntityManagerFactory emf = Persistence.createEntityManagerFactory("restapi");
EntityManager em = emf.createEntityManager();
app.populateDb(em);
ReservationDAO reservationDAO = new ReservationDAO();
List<Reservation> allReservations = reservationDAO.getAllReservations();
System.out.println("allReservations size: " + allReservations.size());
em.clear();
em.close();
emf.close();
}
}
HTTP ERROR 500
Problem accessing /reservation. Reason:
Server Error
Caused by:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:657)
at java.util.ArrayList.get(ArrayList.java:433)
at servlets.ReservationServlet.doGet(ReservationServlet.java:30)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)

in doget method List<Reservation> reservationsList you getting is null. what you can do
if ( reservationsList !=null && !reservationsList.isEmpty())
{
System.out.println("reservationsList size: " + reservationsList.size());
//String json =gson.toJson(reservationsList);
response.getWriter().write(reservationsList.get(0).getPerson().getName()); }
else {
response.getWriter().write("record not found")
}

Related

Class sorting JSON by ID instead of highest value

I'm doing a vote counting system, the winner is the one who has more than 3 votes, however, I'm facing the following problem. When there is more than one place with 3 votes, instead of my JSON returning the one with the most votes, it always returns the one with more than 3 votes ordered by ID.
That is, if the restaurant with ID 1 has 3 votes, and the restaurant with ID 2 has 10 votes, the restaurant with ID 1 ends up appearing on the route /restaurants/winner despite not being the most voted, is there any way I can make the most voted show up?
e.g: return from /restaurants/winner route
{
"id": 1,
"restaurant": "Burger King",
"address": "Av. Ipiranga, 1600",
"website": "https://www.burgerking.com.br/",
"description": "Rede de fast-food famosa com hambúrgueres grelhados, batata frita e milk-shakes.",
"count": 3
}
While McDonalds has 5 votes
{
"id": 2,
"restaurant": "McDonalds",
"address": "Av. Ipiranga, 5200",
"website": "https://www.mcdonalds.com.br/",
"description": "Rede de fast-food tradicional conhecida por ter ótimos hambúrgueres e batatas fritas.",
"count": 5
}
Here are the classes that I'm using:
Restaurant.java
package com.dbserver.restaurantes.entities;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(name = "db_restaurants")
public class Restaurant {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String restaurant;
private String address;
private String website;
private String description;
private Integer count;
#JsonIgnore
#OneToMany(mappedBy = "id.restaurant")
private Set<Vote> votes = new HashSet<>();
public Restaurant() {
}
public Restaurant(Long id, String restaurant, String address, String website, String description, Integer count) {
this.id = id;
this.restaurant = restaurant;
this.address = address;
this.website = website;
this.description = description;
this.count = count;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRestaurant() {
return restaurant;
}
public void setRestaurant(String restaurant) {
this.restaurant = restaurant;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Set<Vote> getVotes() {
return votes;
}
}
RestaurantDTO.java
package com.dbserver.restaurantes.dto;
import com.dbserver.restaurantes.entities.Restaurant;
public class RestaurantDTO {
private Long id;
private String restaurant;
private String address;
private String website;
private String description;
private Integer count;
public RestaurantDTO() {
}
public RestaurantDTO(Long id, String restaurant, String address, String website, String description, Integer count) {
this.id = id;
this.restaurant = restaurant;
this.address = address;
this.website = website;
this.description = description;
this.count = count;
}
public RestaurantDTO(Restaurant restaurantDTO) {
id = restaurantDTO.getId();
restaurant = restaurantDTO.getRestaurant();
address = restaurantDTO.getAddress();
website = restaurantDTO.getWebsite();
description = restaurantDTO.getDescription();
count = restaurantDTO.getCount();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getRestaurant() {
return restaurant;
}
public void setRestaurant(String restaurant) {
this.restaurant = restaurant;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
RestaurantServices.java
package com.dbserver.restaurantes.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.dbserver.restaurantes.dto.RestaurantDTO;
import com.dbserver.restaurantes.entities.Restaurant;
import com.dbserver.restaurantes.exceptions.NotFoundException;
import com.dbserver.restaurantes.repositories.RestaurantRepository;
#Service
public class RestaurantServices {
#Autowired
private RestaurantRepository repository;
#Transactional(readOnly = true)
public Page<RestaurantDTO> findAll(Pageable pageable) {
Page<Restaurant> result = repository.findAll(pageable);
Page<RestaurantDTO> page = result.map(x -> new RestaurantDTO(x));
return page;
}
#Transactional(readOnly = true)
public RestaurantDTO findById(Long id) {
Restaurant result = repository.findById(id).get();
RestaurantDTO dto = new RestaurantDTO(result);
return dto;
}
#Transactional(readOnly = true)
public Restaurant findWinner(Integer count) {
List<Restaurant> restaurants = repository.findAll();
for (Restaurant restaurant : restaurants) {
// Hibernate.initialize(restaurant.getCount());
if (restaurant.getCount() >= 3) {
return restaurant;
}
}
throw new NotFoundException(
"Nenhum restaurante ganhou a votação, é necessário um total de 3 votos para ter um restaurante vencedor.");
}
#Transactional
public Restaurant addRestaurant(Restaurant newRestaurant) {
return repository.saveAndFlush(newRestaurant);
}
}
RestaurantRepository.java
package com.dbserver.restaurantes.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import com.dbserver.restaurantes.entities.Restaurant;
public interface RestaurantRepository extends JpaRepository<Restaurant, Long> {
}
RestaurantController.java
package com.dbserver.restaurantes.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.dbserver.restaurantes.dto.RestaurantDTO;
import com.dbserver.restaurantes.entities.Restaurant;
import com.dbserver.restaurantes.services.RestaurantServices;
#RestController
#RequestMapping(value = "/restaurants")
public class RestaurantController {
#Autowired
private RestaurantServices service;
#GetMapping
public Page<RestaurantDTO> findAll(Pageable pageable) {
return service.findAll(pageable);
}
#GetMapping(value = "/{id}")
public RestaurantDTO findById(#PathVariable Long id) {
return service.findById(id);
}
#GetMapping(value = "/winner")
public Restaurant findWinner(Integer count) {
return service.findWinner(count);
};
#PostMapping
public Restaurant addRestaurant(#RequestBody Restaurant newRestaurant) {
return service.addRestaurant(newRestaurant);
}
}
You have to check the top value as well. So You need to add your own query for that. Here is the code
public interface RestaurantRepository extends JpaRepository<Restaurant, Long>
{
Optional<Restaurant> findFirstByCountGreaterThanEqualOrderByCountDesc (Integer count);
}
and Use that inside your method
#Transactional(readOnly = true)
public Restaurant findWinner(Integer count) throws NotFoundException
{
Optional<Restaurant> data = repository.findFirstByCountGreaterThanEqualOrderByCountDesc(3);
if (data.isPresent())
{
return data.get();
}
throw new NotFoundException("Nenhum restaurante ganhou a votação, é necessário um total de 3 votos para ter um restaurante vencedor.");
}
You can use native queries as well.

How to return the genarated ID in CrudDAOImpl.java when using Hibernate-JPA

I use the hibernate-JPA implementation (v5.6.1.Final) in my project.
I have implemented the data access layer as follows:
Class Visualization Diagram.
1.1 Employee.java Entity
package com.elephasvacation.tms.web.entity;
import com.elephasvacation.tms.web.entity.enumeration.GenderTypes;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
#Entity
#Table(name = "employee")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Employee implements SuperEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#Column(name = "name", nullable = false, length = 200)
private String name;
#Lob
#Column(name = "address")
private String address;
#Column(name = "date_of_birth")
private LocalDate dateOfBirth;
#Column(name = "nic", length = 45)
private String nic;
#Column(name = "contact", length = 45)
private String contact;
#Column(name = "email", length = 200)
private String email;
#Column(name = "gender", length = 20)
private GenderTypes gender;
#Column(name = "position", length = 45)
private String position;
#Column(name = "status", length = 45)
private String status;
#Column(name = "created")
private LocalDateTime created;
#Column(name = "updated")
private LocalDateTime updated;
/* Constructor with ID attribute. */
public Employee(Integer id,
String name,
String address,
LocalDate dateOfBirth,
String nic,
String contact,
String email,
GenderTypes gender,
String position,
String status) {
this.id = id;
this.name = name;
this.address = address;
this.dateOfBirth = dateOfBirth;
this.nic = nic;
this.contact = contact;
this.email = email;
this.gender = gender;
this.position = position;
this.status = status;
}
/* Constructor without ID attribute. */
public Employee(String name,
String address,
LocalDate dateOfBirth,
String nic,
String contact,
String email,
GenderTypes gender,
String position,
String status) {
this.name = name;
this.address = address;
this.dateOfBirth = dateOfBirth;
this.nic = nic;
this.contact = contact;
this.email = email;
this.gender = gender;
this.position = position;
this.status = status;
}
#PrePersist
public void creationTimeStamps() {
created = LocalDateTime.now();
}
#PreUpdate
public void updateTimeStamps() {
updated = LocalDateTime.now();
}
}
I want to return the Generated ID when an object is persisted successfully. So, I Implemented EmployeeDAOImpl.java as follows:
1.2 EmployeeDAOImpl.java
package com.elephasvacation.tms.web.dal.custom.impl;
import com.elephasvacation.tms.web.dal.custom.EmployeeDAO;
import com.elephasvacation.tms.web.entity.Employee;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeDAOImpl implements EmployeeDAO {
private EntityManager entityManager;
#Override
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public Integer save(Employee employee) throws Exception {
this.entityManager.persist(employee);
// call the flush method on EntityManager manually, because we need to get the Generated ID
this.entityManager.flush();
return employee.getId(); // here, generated ID will be returned.
}
#Override
public void update(Employee employee) throws Exception {
this.entityManager.merge(employee);
}
#Override
public void delete(Integer key) throws Exception {
this.entityManager.remove(this.entityManager.find(Employee.class, key));
}
#Override
public Employee get(Integer key) throws Exception {
return this.entityManager.find(Employee.class, key);
}
#Override
public List<Employee> getAll() throws Exception {
Query allEmployeesQuery = this.entityManager.createQuery("SELECT e FROM Employee e");
return (List<Employee>) allEmployeesQuery.getResultList();
}
}
I am refactoring the code as follows:
by creating CrudDAOImpl.java
Class Visualization Diagram After Using CrudDAOImpl.java
2.1 CrudDAOImpl.java
package com.elephasvacation.tms.web.dal;
import com.elephasvacation.tms.web.entity.SuperEntity;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
public class CrudDAOImpl<T extends SuperEntity, K extends Serializable> implements CrudDAO<T, K> {
private EntityManager entityManager;
private Class<T> entityClass;
public CrudDAOImpl() {
this.entityClass =
(Class<T>) (((ParameterizedType) (this.getClass().getGenericSuperclass())).getActualTypeArguments()[0]);
}
/** This method is used to pass the EntityManager to the lower level classes that extend the CrudDAOImpl class.
* */
protected EntityManager getEntityManager(){
return this.entityManager;
}
#Override
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public Integer save(T entity) throws Exception {
/* If native hibernate is used in my project. I can do something like this;
this will return the generated ID:
* this.session.save(entity);
*
* Since I go with hibernate-JPA implementation I want to do the same thing in this method. */
this.entityManager.persist(entity);
this.entityManager.flush();
return null; // I want to return the generated ID here.
}
#Override
public void update(T entity) throws Exception {
this.entityManager.merge(entity);
}
#Override
public void delete(K key) throws Exception {
this.entityManager.remove(key);
}
#Override
public T get(K key) throws Exception {
return this.entityManager.find(this.entityClass, key);
}
#Override
public List<T> getAll() throws Exception {
TypedQuery<T> query =
this.entityManager.createQuery("SELECT " + (this.entityClass.getName()), this.entityClass);
return query.getResultList();
}
}
I would appreciate it if you could please suggest to me a way to return the generated ID when an object persists in the database. Thanks in advance.
If you are interested here's what I have done. I have used SuperEntity.java as #HasnainAliBohra suggested.
Add a getId() method to SuperEntity.java.
package com.elephasvacation.tms.web.entity;
import java.io.Serializable;
public interface SuperEntity extends Serializable {
<T extends Serializable> T getId();
}
Mostly, generated ID will be a java.lang.Integer, So it is Serializable.
Create a getter for the id attribute in Employee.java. Please note that I have used Project Lombok. So, the #Data annotation generates the getter for the id attribute.
Anyhow, getter method looks like this:
// Employee.java class
public Integer getId() {
return id;
}
Change the save() method in CrudDAOImpl.java as follows:
#Override
public Integer save(T entity) throws Exception {
this.entityManager.persist(entity);
this.entityManager.flush();
return entity.getId(); // Let's return the generated ID here.
}
Testing what I have done (with JUnit4).
package com.elephasvacation.tms.web.dal.custom.impl;
import com.elephasvacation.tms.web.dal.DAOFactory;
import com.elephasvacation.tms.web.dal.DAOTypes;
import com.elephasvacation.tms.web.dal.custom.EmployeeDAO;
import com.elephasvacation.tms.web.entity.Employee;
import com.elephasvacation.tms.web.entity.enumeration.GenderTypes;
import com.elephasvacation.tms.web.util.HibernateUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import java.time.LocalDate;
import static org.junit.Assert.assertNotNull;
public class EmployeeDAOImplTest {
private final EmployeeDAO employeeDAO = DAOFactory.getInstance().getDAO(DAOTypes.EMPLOYEE);
private EntityManagerFactory emf;
private EntityManager em;
#Before
public void setUp() {
try {
/* get EntityManagerFactory. */
this.emf = HibernateUtil.getEntityManagerFactory();
/* creates EntityManager. */
this.em = emf.createEntityManager();
} catch (Exception e) {
e.printStackTrace();
}
}
#After
public void tearDown() {
/* close the EntityManagerFactory and EntityManager. */
if (em != null) {
em.close();
emf.close();
}
}
#Test
public void save() {
try {
/* begins the transaction. */
this.em.getTransaction().begin();
/* set EntityManager. */
this.employeeDAO.setEntityManager(this.em);
/* creates a new Employee object. */
Employee john = new Employee("John Doe",
"New York",
LocalDate.of(1991, 01, 01),
"112233445566",
"03321234567",
"john.test#gmail.com",
GenderTypes.MALE,
"Trainee",
"Active");
/* saving the Employee. */
Integer generatedEmployeeId = this.employeeDAO.save(john);
/* assert */
assertNotNull(generatedEmployeeId);
/* print the generated ID on the terminal. */
System.out.println("Generated Employee ID: " + generatedEmployeeId);
/* committing the transaction. */
this.em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Test case did run successfully and the database record persisted in the employee table.
5.1 Terminal output
5.2 Database record screenshot.
Hope you find something useful, thank you.

Quarkus Hibernate: Entity not updated when changed value provided via method

I use Quarkus + Hibernate to sync data to the DB and I've noticed during testing that sometimes my entity isn't updated. I've created a minimal example adjusting the original example https://github.com/quarkusio/quarkus-quickstarts/tree/main/hibernate-orm-quickstart
Here are my adjustments:
import.sql
DROP TABLE IF EXISTS fruit CASCADE;
CREATE TABLE fruit (
fruitsSequence INT PRIMARY KEY,
name TEXT NOT NULL,
test INT
);
Fruit.java
package org.acme.hibernate.orm;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.google.common.base.Objects;
#Entity
#Table(name = "known_fruits")
public class Fruit {
#Id
#SequenceGenerator(name = "fruitsSequence", sequenceName = "known_fruits_id_seq", allocationSize = 1, initialValue = 10)
#GeneratedValue(generator = "fruitsSequence")
private Integer id;
#Transient
private String name = "";
#Column(name = "test")
private Integer test = -1;
public Fruit() {
}
public Fruit(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "name")
#Access(AccessType.PROPERTY)
public String getChangedName() {
return "a" + name;
}
public String getName() {
return name;
}
public void setTest(Integer test) {
this.test = test;
}
public Integer getTest() {
return test;
}
#Column(name = "name")
#Access(AccessType.PROPERTY)
protected void setChangedName(String name) {
this.name = name.substring(1);
}
public void setName(String name) {
this.name = name;
}
#Override
public int hashCode() {
return Objects.hashCode(name, test);
}
#Override
public boolean equals(Object o) {
if (o instanceof Fruit) {
Fruit other = (Fruit) o;
return name.equals(other.name) && test.equals(other.test);
}
return false;
}
}
Replaced the test withDBTest.java
package org.acme.hibernate.orm;
import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertEquals;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.UserTransaction;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
#QuarkusTest
public class DBTest {
#Inject
EntityManager m_em;
#Inject
UserTransaction m_transaction;
#Test
void testUpdate() throws Exception {
Fruit fruit = given().when().body("{\"name\" : \"Pear\"}").contentType("application/json").post("/fruits")
.then().statusCode(201).extract().as(Fruit.class);
m_transaction.begin();
Fruit db = m_em.find(Fruit.class, fruit.getId());
db.setName("Apple");
db.setTest(13);
m_transaction.commit();
db = m_em.find(Fruit.class, fruit.getId());
assertEquals(13, db.getTest(), "Unexpected test");
assertEquals("Apple", db.getName(), "Unexpected name");
}
#Test
void testUpdateLongName() throws Exception {
Fruit fruit = given().when().body(
"{\"name\" : \"PeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDBaaaaaaaaaaaaaar\"}")
.contentType("application/json").post("/fruits").then().statusCode(201).extract().as(Fruit.class);
m_transaction.begin();
Fruit db = m_em.find(Fruit.class, fruit.getId());
db.setName(fruit.getName() + "Apple");
db.setTest(13);
m_transaction.commit();
db = m_em.find(Fruit.class, fruit.getId());
assertEquals(13, db.getTest(), "Unexpected test");
assertEquals(fruit.getName() + "Apple", db.getName(), "Unexpected name");
}
#Test
void testUpdateNameOnly() throws Exception {
Fruit fruit = given().when().body("{\"name\" : \"Pear\"}").contentType("application/json").post("/fruits")
.then().statusCode(201).extract().as(Fruit.class);
m_transaction.begin();
Fruit db = m_em.find(Fruit.class, fruit.getId());
db.setName("Apple");
m_transaction.commit();
db = m_em.find(Fruit.class, fruit.getId());
assertEquals(-1, db.getTest(), "Unexpected test");
assertEquals("Apple", db.getName(), "Unexpected name");
}
#Test
void testUpdateNameOnlyREST() throws Exception {
Fruit fruit = given().when().body("{\"name\" : \"Pear\"}").contentType("application/json").post("/fruits")
.then().statusCode(201).extract().as(Fruit.class);
given().when().body("{\"name\" : \"Apple\"}").contentType("application/json").put("/fruits/" + fruit.getId())
.then().statusCode(200).extract().as(Fruit.class);
Fruit db = m_em.find(Fruit.class, fruit.getId());
assertEquals(-1, db.getTest(), "Unexpected test");
assertEquals("Apple", db.getName(), "Unexpected name");
}
}
What I see is that testUpdateNameOnly and testUpdateNameOnlyREST fail whereas the other tests run as expected. In my original testcase, even changing another field didn't update the TEXT field hence the test with the long name. The reason why the name is altered when writing it to the DB is to encrypt it (the outcome is a BASE64 string).
I am not sure if this is a configuration issue or an actual bug.
Thanks for helps in advance!
As suggested by the comments this seems to be a bug (https://github.com/quarkusio/quarkus/issues/16619).
It works with the AttributeConver:
Fruit.java:
package org.acme.hibernate.orm;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import com.google.common.base.Objects;
#Entity
#Table(name = "known_fruits")
public class Fruit {
#Id
#SequenceGenerator(name = "fruitsSequence", sequenceName = "known_fruits_id_seq", allocationSize = 1, initialValue = 10)
#GeneratedValue(generator = "fruitsSequence")
private Integer id;
#Column(name = "name")
#Convert(converter = NameConverter.class)
private String name = "";
#Column(name = "test")
private Integer test = -1;
public Fruit() {
}
public Fruit(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setTest(Integer test) {
this.test = test;
}
public Integer getTest() {
return test;
}
public void setName(String name) {
this.name = name;
}
#Override
public int hashCode() {
return Objects.hashCode(name, test);
}
#Override
public boolean equals(Object o) {
if (o instanceof Fruit) {
Fruit other = (Fruit) o;
return name.equals(other.name) && test.equals(other.test);
}
return false;
}
}
NameConverter.java:
package org.acme.hibernate.orm;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
#Converter
public class NameConverter implements AttributeConverter<String, String> {
#Override
public String convertToDatabaseColumn(String name) {
return "a" + name;
}
#Override
public String convertToEntityAttribute(String name) {
return name.substring(1);
}
}

How to enum mapping with jpa Spring boot why not save enum value in DB in DB saving enum key

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
import org.hibernate.annotations.GenericGenerator;
import com.lue.billingsystem.enums.Status;
import com.lue.billingsystem.enums.Types;
#Entity
#Table(name="product_tab")
public class Product implements Serializable{
private static final long serialVersionUID = 8919320309645697466L;
#Id
#Column(name="prod_id",updatable=false)
#GenericGenerator(name="product_tab_genetator",strategy="increment")
#GeneratedValue(generator="product_tab_genetator")
private Long id;
private String name;
#Enumerated(EnumType.STRING)
#Column(name = "type")
private Types type;
#Column(name = "status")
#Enumerated(EnumType.STRING)
private Status status;
#Column(name = "description", length = 200)
private String description;
#OneToMany(mappedBy="product")
private List<Charge> charges;
#Column(name = "create_date", columnDefinition = "DATETIME")
private Date createDate;
#Column(name = "update_date", columnDefinition = "DATETIME")
private Date updateDate;
//#Version
private Integer version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Types getType() {
return type;
}
public void setType(Types type) {
this.type = type;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Charge> getCharges() {
return charges;
}
public void setCharges(List<Charge> charges) {
this.charges = charges;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
import org.springframework.http.HttpStatus;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.lue.billingsystem.enums.utils.StatusDeserializer;
import com.lue.billingsystem.exception.BillingException;
#JsonDeserialize(using = StatusDeserializer.class)
public enum Status {
ACTIVE("Active"), INACTIVE("Inactive");
private final String text;
Status(final String text) {
this.text = text;
}
#Override
public String toString() {
return text;
}
public String getText() {
return this.text;
}
public static Status fromText(String text) {
for (Status r : Status.values()) {
if (r.getText().equals(text)) {
System.out.println(r);
return r;
}
}
throw new BillingException("Your Status not valied: "+text +" ", HttpStatus.BAD_REQUEST, 400);
}
}
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.lue.billingsystem.enums.Status;
public class StatusDeserializer extends JsonDeserializer<Status> {
#Override
public Status deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
if (node == null) {
return null;
}
String text = node.textValue(); // gives "A" from the request
if (text == null) {
return null;
}
//System.out.println(Status.fromText(text) + "---------------");
return Status.fromText(text);
}
}
How to enum mapping with jpa Spring boot why not save enum value in DB in DB saving enum key when i saving product in databse not save status like Active it always save ACTIVE
You just need to pay attention to the enum values when the table is being created.
What are the enum values in the table e.g. in status column, are the values defined as 'Active', 'Inactive' or 'ACTIVE', 'INACTIVE'. That's what will determine the value saved.
If the enum values are defined as 'ACTIVE', 'INACTIVE', if you insert 'active' as the value for status, it will change to 'ACTIVE' inside the database because it inserts based on the pre defined enum values.

Join in hibernate with annotaion

I am trying to perform join in hibernate and i am using struts2.
I am working with hibernate using annotaions. Now i am unable to perform join between two tables.My first table is "studentprojects" which contain pid and email.Second table is "initialprojectdetials" which contains pid,name,description... similarly some other fields.I have to get the data of second table by performing join around pid of first table.
For this am using this query:
String hql="from InitialProjectDTO I join I.projectId S where I.projectId=:id";
Query query=session.createQuery(hql);
query.setParameter("id", id);
mail =query.list();
where mail is the arraylist of InitialProjectDTO.
And my InitialProjectDTO is:
package edu.pma.dto;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="initialprojectdetail")
public class InitialProjectDTO {
#Id
#Column(name="projectId")
#OneToMany(cascade=CascadeType.ALL)
#JoinTable(name="studentprojects",joinColumns=#JoinColumn(name="projectId"))
int projectId;
#Column(name="name")
String name;
#Column(name="description")
String description;
#Column(name="technology")
String technology;
#Column(name="guide")
String guide;
#Column(name="duration")
int duration;
#Column(name="status")
String status;
#Column(name="report")
String report;
public String getReport() {
return report;
}
public void setReport(String report) {
this.report = report;
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTechnology() {
return technology;
}
public void setTechnology(String technology) {
this.technology = technology;
}
public String getGuide() {
return guide;
}
public void setGuide(String guide) {
this.guide = guide;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
my SudentProjectDTO is:
package edu.pma.dto;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="studentprojects")
public class StudentProjectDTO {
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
#Id
#Column(name="email")
String email;
#Column(name="projectId")
int projectId;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
This is the error which i am getting:
Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: edu.pma.dto.InitialProjectDTO.projectId
Method "execute" failed for object edu.pma.actions.LoginAction#1096a56
File: org/hibernate/cfg/annotations/CollectionBinder.java
You should try to use different models
#Entity
public class InitialProjectDTO {
#OneToMany(mappedBy = "project")
private Collection<StudentProjectDTO> students;
}
#Entity
public class StudentProjectDTO {
#ManyToOne
private InitialProjectDTO project;
}
And with the proper model it shuld be easy to write hql, you might want to look here for examples https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html.
Also I would suggest to look here for example of models. http://viralpatel.net/blogs/hibernate-one-to-many-annotation-tutorial/
See following example might its help to you
#Entity
#Table(name="initialprojectdetail")
public class InitialProjectDTO {
private Integer initialProjectDTOId;
private Set<StudentProjectDTO > studentProjectDTO = new HashSet<StudentProjectDTO >(0);
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "initial_projectDTO_id", unique = true, nullable = false)
public Integer getInitialProjectDTOId() {
return this.initialProjectDTOId;
}
public void setInitialProjectDTOId(Integer initialProjectDTOId) {
this.initialProjectDTOId = initialProjectDTOId;
}
#OneToMany(mappedBy = "studentprojects", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Set<StudentProjectDTO> getUserRole() {
return this.studentProjectDTO;
}
public void setUserRole(Set<StudentProjectDTO> studentProjectDTO) {
this.studentProjectDTO = studentProjectDTO;
}
}
#Entity
#Table(name="studentprojects")
public class StudentProjectDTO {
private InitialProjectDTO project;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "initial_projectDTO_id", nullable = false)
public User getProject() {
return this.project;
}
public void setProject(InitialProjectDTO project) {
this.project = project;
}
}
your Query shoud be something like this
String hql="SELECT ip from InitialProjectDTO ip JOIN ip.studentProjectDTO sp WHERE sp.projectId = :id";
Query query=session.createQuery(hql);
query.setParameter("id", id);
mail =query.list();

Categories