1 to1 relationship causing , Exception :org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update - spring

Technologies used: Spring MVC , Hibernate , MySQL DB, Windows 7, NetBeans IDE
My create,read,update operations, work however Im getting an Exception when trying to delete UserAccount & associated password record:
SEVERE: Cannot delete or update a parent row: a foreign key constraint fails (profiler.password, CONSTRAINT FK4C641EBBCF6D23F4 FOREIGN KEY (user_id) REFERENCES user_account (user_id))
Oct 10, 2012 11:52:22 AM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (profiler.password, CONSTRAINT FK4C641EBBCF6D23F4 FOREIGN KEY (user_id) REFERENCES user_account (user_id))
UserAccount & Password relationship:
UserAccount class:
package com.profile.beans;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import javax.persistence.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
#Entity
#Table(name = "user_account")
public class UserAccount implements Serializable {
#Autowired
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "user_account_seq")
#SequenceGenerator(name = "user_account_seq", sequenceName = "user_account_seq")
#Column(name = "user_id")
private Long userId ;
//
#Autowired
#Column(name = "user_name")
private String userName;
//
#Autowired
#Column(name = "user_type")
private String userType;
//
#Autowired
#Column(name = "first_name")
private String firstName;
//
#Autowired
#Column(name = "last_name")
private String lastName;
//
#Autowired
#Column(name = "email")
private String email;
//
#Autowired
#Column(name = "phone_contact")
private String phoneContact;
//
#Autowired
#Column(name = "address")
private String address;
//
#Autowired
#Column(name = "city")
private String city ;
//
#Autowired
#Column(name = "state")
private String state;
//
#Autowired
#Column(name = "country")
private String country;
//
#Autowired
#Column(name = "zipcode")
private Integer zipcode = 0;
//is the user account Active either due to user deactivation,admin deactivation, or nonpayment
#Autowired
#Column(name = "active")
private boolean active = false;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "UserAccount")
#JoinColumn(name="user_id")
private Password Password = null;
#OneToMany(mappedBy="UserAccount",cascade={CascadeType.ALL})
#JoinColumn(name="doc_id")
private List<Document> documents = null;
#Autowired(required = false)
public UserAccount() {
}
#Autowired(required = true)
public UserAccount(Long userId, String userName, String userType, String firstName, String lastName, String email, String phoneContact, String address, String city, String state, String country, Integer zipcode) {
this.userId = userId;
this.userName = userName;
this.userType = userType;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.phoneContact = phoneContact;
this.address = address;
this.city = city;
this.state = state;
this.country = country;
this.zipcode = zipcode;
}
public com.profile.beans.Password getPassword() {
return Password;
}
public void setPassword(com.profile.beans.Password Password) {
this.Password = Password;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Document> getDocuments() {
return documents;
}
public void setDocuments(List<Document> documents) {
this.documents = documents;
}
public Integer getZipcode() {
return zipcode;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneContact() {
return phoneContact;
}
public void setPhoneContact(String phoneContact) {
this.phoneContact = phoneContact;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
public void setZipcode(Integer zipcode) {
try
{
this.zipcode = zipcode;
}
catch (NumberFormatException exc)
{
exc.printStackTrace();
}
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UserAccount other = (UserAccount) obj;
if ((this.userId == null) ? (other.userId != null) : !this.userId.equals(other.userId)) {
return false;
}
return true;
}
#Override
public int hashCode() {
int hash = 3;
hash = 73 * hash + (this.userId != null ? this.userId.hashCode() : 0);
return hash;
}
#Override
public String toString() {
return "UserAccount{" + "userId=" + userId + ", userName=" + userName + ", userType=" + userType + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + ", phoneContact=" + phoneContact + ", address=" + address + ", city=" + city + ", state=" + state + ", country=" + country + ", zipcode=" + zipcode + ", active=" + active + ", documents=" + documents + '}';
}
}
Password class :
package com.profile.beans;
import java.io.Serializable;
import javax.persistence.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.hibernate.annotations.Cascade;
#Entity
#Table(name = "Password")
public class Password implements Serializable {
#Autowired(required = false)
public Password() {
}
#Autowired(required = true)
public Password(UserAccount UserAccount) {
this.UserAccount = UserAccount;
}
#Autowired
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "password_seq")
#SequenceGenerator(name = "password_seq", sequenceName = "password_seq")
#Column(name = "password_id")
private Long passwordId;
#Autowired
#Column(name = "password")
private String password = null;
//1 to 1 relation with UserAccounts
//1 to 1 relation with UserAccounts
#Autowired
#Qualifier("UserAccount")
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_id", referencedColumnName="user_id",nullable = false)
private UserAccount UserAccount;
#Autowired(required = true)
public Password(UserAccount UserAccount, String password) {
this.UserAccount = UserAccount;
this.password = password;
}
public UserAccount getUserAccount() {
return UserAccount;
}
public void setUserAccount(UserAccount UserAccount) {
this.UserAccount = UserAccount;
}
public Long getPasswordId() {
return passwordId;
}
public void setPasswordId(Long passwordId) {
this.passwordId = passwordId;
}
public String getPassword() {
return password;
}
}
My database DDL (MySQL syntax):
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
DROP SCHEMA IF EXISTS `profiler`;
CREATE SCHEMA IF NOT EXISTS `profiler` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
DROP SCHEMA IF EXISTS `profiler` ;
CREATE SCHEMA IF NOT EXISTS `profiler` DEFAULT CHARACTER SET latin1 ;
USE `profiler` ;
-- -----------------------------------------------------
-- Table `profiler`.`user_account`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `profiler`.`user_account` ;
CREATE TABLE IF NOT EXISTS `profiler`.`user_account` (
`user_id` BIGINT(20) NOT NULL ,
`user_name` VARCHAR(45) NULL DEFAULT NULL ,
`user_type` VARCHAR(45) NULL DEFAULT NULL ,
`first_name` VARCHAR(45) NULL DEFAULT NULL ,
`last_name` VARCHAR(45) NULL DEFAULT NULL ,
`email` VARCHAR(45) NULL DEFAULT NULL ,
`phone_contact` VARCHAR(45) NULL DEFAULT NULL ,
`address` VARCHAR(45) NULL DEFAULT NULL ,
`city` VARCHAR(45) NULL DEFAULT NULL ,
`state` VARCHAR(45) NULL DEFAULT NULL ,
`country` VARCHAR(45) NULL DEFAULT NULL ,
`zipcode` VARCHAR(45) NULL DEFAULT NULL ,
`active` TINYINT(1) NULL DEFAULT NULL ,
PRIMARY KEY (`user_id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `profiler`.`document`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `profiler`.`document` ;
CREATE TABLE IF NOT EXISTS `profiler`.`document` (
`doc_id` BIGINT(20) NOT NULL ,
`title` VARCHAR(45) NULL DEFAULT NULL ,
`format` VARCHAR(45) NULL DEFAULT NULL ,
`url_string` VARCHAR(45) NULL DEFAULT NULL ,
`size_in_bytes` INT(11) NULL DEFAULT NULL ,
`created_on` TIMESTAMP NULL DEFAULT NULL ,
`bytes` BLOB NULL DEFAULT NULL ,
`height` INT(11) NULL DEFAULT NULL ,
`width` INT(11) NULL DEFAULT NULL ,
`user_id` BIGINT(20) NOT NULL ,
PRIMARY KEY (`doc_id`) ,
CONSTRAINT `user_id_fk`
FOREIGN KEY (`user_id` )
REFERENCES `profiler`.`user_account` (`user_id` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `profiler`.`password`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `profiler`.`password` ;
CREATE TABLE IF NOT EXISTS `profiler`.`password` (
`password_id` BIGINT(20) NOT NULL ,
`password` VARCHAR(45) NOT NULL ,
`user_id` BIGINT(20) NOT NULL ,
PRIMARY KEY (`password_id`) ,
CONSTRAINT `user_id_fk_1`
FOREIGN KEY (`user_id` )
REFERENCES `profiler`.`user_account` (`user_id` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
CREATE INDEX `user_id_fk_idx` ON `profiler`.`password` (`user_id` ASC) ;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
SET foreign_key_checks = 1;
UserAccount controller class:
#Controller
#RequestMapping("/UserAccount")
public class UserAccountController {
#Autowired
private UserAccountDao userAccountDao;
#Autowired
private PasswordDao passwordDao;
public UserAccountController() {
}
public UserAccountController(UserAccountDao userAccountDao, PasswordDao passwordDao) {
this.userAccountDao = userAccountDao;
this.passwordDao = passwordDao;
}
#RequestMapping(value="/Register")
public String RegisterationView()
{
return "UserAccount/Register";
}
#RequestMapping(value="/Login")
public String LoginView()
{
return "UserAccount/Login";
}
#RequestMapping(value="/Update")
public String UpdateView()
{
return "UserAccount/Update";
}
//create
#RequestMapping(value="/create",method = RequestMethod.POST)
public String create(
#RequestParam("username") String username,
#RequestParam("email") String email,
#RequestParam("firstname") String firstName,
#RequestParam("lastname") String lastName,
#RequestParam("phonecontact") String phonecontact,
#RequestParam("address") String address,
#RequestParam("state") String state,
#RequestParam("city") String city,
#RequestParam("country") String country,
#RequestParam("password") String password,
#RequestParam("zipcode") Integer zipcode,
HttpSession session,HttpServletRequest request, Model model)
{
String view = null ;
//*check if username exists
//*if email exists
UserAccount userAccount = new UserAccount();
userAccount.setAddress(address);
userAccount.setCity(city);
userAccount.setCountry(country);
userAccount.setState(state);
userAccount.setPhoneContact(phonecontact);
userAccount.setEmail(email);
userAccount.setZipcode(zipcode);
userAccount.setFirstName(firstName);
userAccount.setLastName(lastName);
userAccount.setUserName(username);
userAccount.setUserType(utility.UserTypes.REGULAR);
//instatiate password
//**password not exist before & must be at least characters long
Password userPassword = new Password(userAccount,password);
userAccountDao.create(userAccount);
passwordDao.create(userPassword);
//add userAccount to model
model.addAttribute("userAccount", userAccount);
session.setAttribute("userAccount", userAccount);
view = "UserAccount/UserMainMenu";
return view;
}
//update
#RequestMapping(value="/update",method = RequestMethod.GET)
public String update( #RequestParam(value="username", required=false) String username,
#RequestParam(value="email",required=false) String email,
#RequestParam(value="firstname",required=false) String firstName,
#RequestParam(value="lastname",required=false) String lastName,
#RequestParam(value="phonecontact",required=false) String phonecontact,
#RequestParam(value="address",required=false) String address,
#RequestParam(value="state",required=false) String state,
#RequestParam(value="city",required=false) String city,
#RequestParam(value="country",required=false) String country,
#RequestParam(value="zipcode",required=false) Integer zipcode,#RequestParam(value="update",required=false) String update,HttpSession session,HttpServletRequest request)
{
String view = null ;
UserAccount userAccount = (UserAccount)session.getAttribute("userAccount");
//*check if username exists
//*if email exists
try
{
System.out.println("Class UserAccountController, update:" + update);
if (update.equalsIgnoreCase("update"))
{
//reset values in case updated info
userAccount.setAddress(address);
userAccount.setCity(city);
userAccount.setCountry(country);
userAccount.setState(state);
userAccount.setPhoneContact(phonecontact);
userAccount.setEmail(email);
userAccount.setZipcode(zipcode);
userAccount.setFirstName(firstName);
userAccount.setLastName(lastName);
userAccount.setUserName(username);
userAccount.setUserType(utility.UserTypes.REGULAR);
//instatiate password
userAccountDao.update(userAccount);
//add userAccount to model
session.setAttribute("userAccount", userAccount);
view = "UserAccount/UserMainMenu";
}
if (update.equalsIgnoreCase("delete"))
{
System.out.println("Class UserAccountController, userAccount: "+userAccount);
//query for password that corresponds to particular user
Password password = (Password)passwordDao.getByUserAccount(userAccount);
System.out.println("Class UserAccountController, password: "+password );
password.setUserAccount(null);
//delete password
passwordDao.delete(password);
//delete user account
userAccountDao.delete(userAccount);
session.removeAttribute("userAccount");
view = "UserAccount/UserMainMenu";
}
}
catch (Exception exc)
{
//forward to error page
exc.getMessage();
view = "error";
}
return view;
}
//delete
#RequestMapping(value="/delete",method = RequestMethod.DELETE)
public String delete( #RequestParam("id")Long id,HttpSession session,HttpServletRequest request)
{
String view = null ;
UserAccount newUserAccount = userAccountDao.getById(id);
userAccountDao.delete(newUserAccount);
view = "UserAccount/UserMainMenu";
return view;
}
//read
#RequestMapping(value="/read",method = RequestMethod.GET)
public void read(Long id)
{
userAccountDao.getById(id);
}
public UserAccountDao getUserAccountDao() {
return userAccountDao;
}
public void setUserAccountDao(UserAccountDao userAccountDao) {
this.userAccountDao = userAccountDao;
}
public PasswordDao getPasswordDaoImpl() {
return passwordDao;
}
public void setPasswordDaoImpl(PasswordDaoImpl passwordDao) {
this.passwordDao = passwordDao;
}
}
PasswordDaoImpl class:
#Repository
#Transactional
public class PasswordDaoImpl implements PasswordDao{
#Autowired
private SessionFactory sessionFactory;
private Session currentSession()
{
return sessionFactory.getCurrentSession();
}
#Override
public Password getByUserAccount(UserAccount UserAccount) {
String hql = "FROM com.profile.beans.Password WHERE Password.UserAccount.UserId =:id";
Long id = UserAccount.getUserId();
Query q = currentSession().createQuery(hql);
return (Password)q.setParameter("id",id).list().get(0);
}
#Override
public void create(Password Password) {
currentSession().save(Password);
}
#Override
public void delete(Password Password) {
currentSession().delete(Password);
}
#Override
public void update(Password Password) {
currentSession().update(Password);
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}

You should break the relationship before you delete UserAccount:
Password pass = userAccount.getPassword();
userAccount.setPassword(null);
userAccountDao.delete(pass);
userAccountDao.delete(userAccount);

Related

Spring Boot test #After not deleting rows before next test

I have the following #Before and #After in my Spring Boot integration tests:
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilter(springSecurityFilterChain).build();
user = userRepository.save(
new User("Joe", "Bloggs", "joe#example.com", "joe", passwordEncoder.encode("secret")));
currency = currencyRepository.save(
new Currency("GBP", "£%01.2f"));
fund = fundRepository.save(
new Fund("Nationwide", (double) 100, currency));
}
#After
public void teardown() {
userRepository.delete(user);
currencyRepository.delete(currency);
fundRepository.delete(fund);
}
However, it doesn't seem that currencies are being deleted after each test and my tests are failing in error:
...
[ERROR] testGetFunds_whenNoToken_thenUnauthorized(biz.martyn.budget.FundsControllerTest) Time elapsed: 3.268 s <<< ERROR!
org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find biz.martyn.budget.currency.Currency with id 437; nested exception is javax.persistence.EntityNotFoundException: Unable to find biz.martyn.budget.currency.Currency with id 437
Caused by: javax.persistence.EntityNotFoundException: Unable to find biz.martyn.budget.currency.Currency with id 437
...
After, if I query the test database, I see that rows haven't been deleted:
mysql> select * from currencies;
+----+---------------------+---------------------+---------------+------+---------------------+
| id | created_at | deleted_at | format | name | updated_at |
+----+---------------------+---------------------+---------------+------+---------------------+
...
| 437 | 2020-01-02 13:51:24 | 2020-01-02 13:51:23 | £%01.2f | GBP | 2020-01-02 13:51:24 |
...
+----+---------------------+---------------------+---------------+------+---------------------+
5 rows in set (0.00 sec)
There should only be one unique entry for name but I guess as delete is not happening it is pulling duplicates for "GBP". My repository for currencies:
Currency.java
#Entity(name = "currencies")
#SQLDelete(sql = "UPDATE currencies SET deleted_at = now() WHERE id = ?")
#Where(clause = "deleted_at is null")
public class Currency {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
protected Integer id;
#Column(unique = true, nullable = false)
private String name;
#Column(nullable = false)
private String format;
#Column(name = "created_at", updatable = false)
#CreationTimestamp
protected LocalDateTime createdAt;
#Column(name = "updated_at")
#UpdateTimestamp
protected LocalDateTime updatedAt;
#Column(name = "deleted_at")
protected LocalDateTime deletedAt;
protected Currency() {}
public Currency(String name, String format) {
this.name = name;
this.format = format;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getFormat() {
return format;
}
public void setFormat(final String format) {
this.format = format;
}
}
User.java
#Entity(name = "users")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = -8507204786382662588L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String firstName;
#Column(nullable = false)
private String surname;
#Column(nullable = false, unique = true)
private String email;
#Column(nullable = false, unique = true)
private String username;
#Column(nullable = false)
#JsonIgnore
private String password;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name="user_id")
#JsonIgnore
private List<Fund> funds;
protected User() {}
public User(String firstName, String surname, String email, String username, String password) {
this.firstName = firstName;
this.surname = surname;
this.email = email;
this.username = username;
this.password = password;
}
public Long getId() {
return id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// standard getters and setters
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Fund> getFunds() {
return funds;
}
public void addFund(Fund fund) {
funds.add(fund);
fund.setUser(this);
}
public void removeFund(Fund fund) {
funds.remove(fund);
fund.setUser(null);
}
// public Fund getFund(int id) {
// fundRepository.findByIdAndUserId(id)
// .orElseThrow(() -> new EntityNotFoundException("Fund ID not found: "+id));
// }
}
The delete method takes an object of Currency. Your Currency object has an ID which is auto-generated.
When you pass the same object that you passed to save to delete you did not set the ID that's the reason the delete operation never actually deletes the data you wanted to delete.
You can either use the object that is returned from save method or get a hold of the genearted-id and use deleteById method.
Here is an example for delete using the object.
#Before
public void setup() {
user = repository.save(user);
}
#After
public void tearDown() {
repository.delete(user);
}
Alternatively, you can use the same object to get the generated-id and use deleteById method.
If you take a look at SimpleJpaRepository which provides an implementation for JPA, you will find that if your ID is null then they are treated as a new entity and are never deleted.
/*
* (non-Javadoc)
* #see org.springframework.data.repository.CrudRepository#delete(java.lang.Object)
*/
#Override
#Transactional
#SuppressWarnings("unchecked")
public void delete(T entity) {
Assert.notNull(entity, "Entity must not be null!");
if (entityInformation.isNew(entity)) {
return;
}
// Other stuff
}

I'm trying to implement group by on a table and want to implement it from repository

I've a table tbl_rating, I'm trying to get avg o=rating of the users that are existing in this table.
This is the table I have.
CREATE TABLE `tbl_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`email` varchar(255) NOT NULL,
`contact` varchar(255) NOT NULL,
`status` enum('active','inactive') NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `contact` (`contact`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1
this is the tbl_rating
CREATE TABLE `tbl_rating` (
`id` bigint(255) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL,
`point` int(1) NOT NULL,
`status` enum('active','inactive') NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
this is the query that I'm trying to implement from repository.
SELECT r.user_id, u.name, AVG(r.point) AS average
FROM tbl_rating r LEFT JOIN tbl_user u ON u.id=r.user_id
GROUP BY r.user_id;
this is my controller
#RequestMapping(value = "/user/rating/avg/individual", method = RequestMethod.POST)
public JsonNode getAvgRatingOfIndividual(HttpServletRequest httpServletRequest) throws IOException {
JSONArray response = new JSONArray();
List<Rating> ratings = new ArrayList<>();
try {
ratings = ratingService.getAvgRatingOfIndividual();
if (ratings.size() > 0) {
} else {
response = new JSONArray();
}
} catch (Exception e) {
return objectMapper.readTree(utility.createResponse(500, KeyWord.ERROR, e.toString()).toString());
}
return objectMapper.readTree(response.toString());
}
following are the service and repository where I'm stuck
service
public List<Rating> getAvgRatingOfIndividual() {
return ratingRepository.??
}
repository
#Repository
public interface RatingRepository extends JpaRepository<Rating, Long> {
}
rating model
#Entity
#Table(name = "tbl_rating")
public class Rating {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
long id;
#ManyToOne
#JoinColumn(name = "user_id")
User user;
#Column(name = "point")
int point;
#Column(name = "status")
String status;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public int getPoint() {
return point;
}
public void setPoint(int point) {
this.point = point;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
user model
#Entity
#Table(name = "tbl_user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
long id;
#Column(name = "name")
String name;
#Column(name = "email")
String email;
#Column(name = "contact")
String contact;
#Column(name = "status")
String status;
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
}
would appreciate if i could get any sort of help on this native query writing in spring boot repository
You can use from a DTO and fill it implicitly in repository.
package com.test.dto;
#Value
public class RatingDTO{
private Long userId;
private String name;
private Double average;
}
And in the repository class:
//RatingRepository.java
#Repository
public interface RatingRepository extends JpaRepository<Rating, Long> {
#Query("SELECT new com.test.dto.RatingDTO(R.user.id, R.user.name, AVG(R.point)) FROM Rating R GROUP BY R.user.id")
List<RatingDTO> getAveragePoints();
}

how can I find last 7 days data using spring data JPA?

I want to find last 7 orders form order table, how am I supposed to do that?
Here's the order table
CREATE TABLE `orders` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`total` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`service_charge` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`vat` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`delivery_charge` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`subtotal` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`point_used` int(5) DEFAULT NULL,
`discount_id` bigint(20) DEFAULT NULL,
`user_id` bigint(20) NOT NULL,
`address_id` bigint(20) NOT NULL,
`payement_type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`payment_status` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`message` mediumtext COLLATE utf8mb4_unicode_ci,
`transaction_id` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`invoice` enum('yes','no') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'no',
`status` enum('pending','accepted','processed','on-way','delivered','cancelled') COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `address_id` (`address_id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
this is the service I'm using
public List<Order> getLastSevenDaysOrders(User user, String todayString, String sevenDaysBeforeString) {
ArrayList<Order> orders = new ArrayList<>();
orderRepository.findByUserAndCreatedAtBetween(user, todayString, sevenDaysBeforeString).forEach(orders::add);
return orders;
}
This is the repository I've.
List<Order> findByUserAndCreatedAtBetween(User user, String todayString, String sevenDaysBeforeString);
This is my controller
#RequestMapping(value = "/order/recent", method = RequestMethod.POST)
public JsonNode getRecentOrder(HttpServletRequest httpServletRequest, #RequestBody String userId) throws IOException {
long startTime = System.currentTimeMillis();
utility.printCallingUrl(httpServletRequest);
JSONObject request = new JSONObject(userId);
JSONArray response = new JSONArray();
//Order order = new Order();
List<Order> orders = new ArrayList<>();
String auth = httpServletRequest.getHeader("Authorization");
String authentication = utility.getBasicAuth();
if (auth.equals(authentication)) {
try {
Calendar calendar = Calendar.getInstance();
String pattern = "yyyy-MM-dd HH:mm:ss";
DateFormat dateFormat = new SimpleDateFormat(pattern);
Date today = calendar.getTime();
String todayString = dateFormat.format(today);
calendar.add(Calendar.DAY_OF_MONTH, -7);
Date sevenDaysBefore = calendar.getTime();
String sevenDaysBeforeString = dateFormat.format(sevenDaysBefore);
User user = userService.getUser(request.getLong("user_id"));
orders = orderService.getLastSevenDaysOrders(user, todayString, sevenDaysBeforeString);
if (orders.size() > 0) {
for (Order order : orders) {
JSONObject response2 = new JSONObject();
response2.put("receiversName", order.getAddress().getReceiversName());
response2.put("address", order.getAddress().getAddress());
response2.put("nearbyLandmark", order.getAddress().getNearbyLandmark());
response2.put("receiversContact", order.getAddress().getReceiversContact());
response2.put("district", order.getAddress().getDistrict().getNameBn());
response2.put("division", order.getAddress().getDivision().getNameBn());
response2.put("village", order.getAddress().getVillage());
response2.put("name", order.getUser().getName());
response2.put("userId", order.getUser().getId());
response2.put("upazilla", order.getAddress().getUpazilla().getNameBn());
response2.put("vat", order.getVat());
response2.put("deliveryCharge", order.getDeliveryCharge());
response2.put("discountAmount", order.getDiscount().getAmount());
response2.put("discountCode", order.getDiscount().getCode());
response2.put("discountName", order.getDiscount().getName());
response2.put("discountId", order.getDiscount().getId());
response2.put("pointUsed", order.getPointUsed());
response2.put("message", order.getMessage());
response2.put("transactionId", order.getTransactionId());
response2.put("createdAt", order.getCreatedAt());
response2.put("total", order.getTotal());
response2.put("serviceCharge", order.getServiceCharge());
response2.put("subtotal", order.getSubtotal());
response2.put("orderId", order.getId());
response2.put("invoice", order.getInvoice());
response2.put("contact", order.getUser().getContact());
response2.put("payementType", order.getPayementType());
response2.put("paymentStatus", order.getPaymentStatus());
response2.put("status", order.getStatus());
response.put(response2);
}
Log log = utility.saveLog(KeyWord.GET_ORDERS, KeyWord.CMS, httpServletRequest, "200", request, new JSONObject().put("data", response), startTime);
if (log != null) {
utility.showMessage("Log inserted successfully with ID " + log.getId());
} else {
utility.showMessage("Log not inserted");
}
} else {
response = new JSONArray();
Log log = utility.saveLog(KeyWord.GET_ORDERS, KeyWord.CMS, httpServletRequest, "500", request, new JSONObject().put("data", response), startTime);
if (log != null) {
utility.showMessage("Log inserted successfully with ID " + log.getId());
} else {
utility.showMessage("Log not inserted");
}
}
} catch (Exception e) {
utility.showMessage(e.toString());
return mapper.readTree(utility.createResponse(500, KeyWord.ERROR, e.toString()).toString());
}
} else {
return mapper.readTree(utility.createResponse(500, KeyWord.ERROR, KeyWord.AUTHENTICATION).toString());
}
return mapper.readTree(response.toString());
}
Order model
#Entity
#Table(name = "orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
#Expose
private long id;
#Column(name = "total")
#Expose
private String total;
#Column(name = "service_charge")
#Expose
private String serviceCharge;
#Column(name = "vat")
#Expose
private String vat;
#Column(name = "delivery_charge")
#Expose
private String deliveryCharge;
#Column(name = "subtotal")
#Expose
private String subtotal;
#Column(name = "point_used")
#Expose
private int pointUsed;
// #Column(name = "discount_id")
// private long discountId;
#ManyToOne
#JoinColumn(name = "discount_id")
#Expose
Discount discount;
#ManyToOne
#Expose
User user;
#OneToOne
#Expose
Address address;
#Column(name = "payement_type")
#Expose
private String payementType;
#Column(name = "payment_status")
#Expose
private String paymentStatus;
#Column(name = "message")
#Expose
private String message;
#Column(name = "transaction_id")
#Expose
private String transactionId;
#Column(name = "invoice")
#Expose
private String invoice;
#Column(name = "status")
#Expose
private String status;
#Column(name = "created_at")
#Expose
private String createdAt;
#Column(name = "updated_at")
#Expose
private String updatedAt;
public Order() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTotal() {
return total;
}
public void setTotal(String total) {
this.total = total;
}
public String getVat() {
return vat;
}
public void setVat(String vat) {
this.vat = vat;
}
public String getServiceCharge() {
return serviceCharge;
}
public void setServiceCharge(String serviceCharge) {
this.serviceCharge = serviceCharge;
}
public String getDeliveryCharge() {
return deliveryCharge;
}
public void setDeliveryCharge(String deliveryCharge) {
this.deliveryCharge = deliveryCharge;
}
public String getSubtotal() {
return subtotal;
}
public void setSubtotal(String subtotal) {
this.subtotal = subtotal;
}
public int getPointUsed() {
return pointUsed;
}
public void setPointUsed(int pointUsed) {
this.pointUsed = pointUsed;
}
public Discount getDiscount() {
return discount;
}
public void setDiscount(Discount discount) {
this.discount = discount;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getPayementType() {
return payementType;
}
public void setPayementType(String payementType) {
this.payementType = payementType;
}
public String getPaymentStatus() {
return paymentStatus;
}
public void setPaymentStatus(String paymentStatus) {
this.paymentStatus = paymentStatus;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getInvoice() {
return invoice;
}
public void setInvoice(String invoice) {
this.invoice = invoice;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(String updatedAt) {
this.updatedAt = updatedAt;
}
}
Order Repository
#Repository
public interface OrderRepository extends PagingAndSortingRepository<Order, Long> {
List<Order> findByUserAndCreatedAtBetween(User user, String todayString, String sevenDaysBeforeString);
}
What am I doing wrong in service while writing method for repository?
I'm getting a blank array. I think I'm doing something wrong when writing findByUserAndCreatedAtBetween. would be great if could get any suggestion.
Your contract
List<Order> findByUserAndCreatedAtBetween(User user, String todayString, String sevenDaysBeforeString);
gets date-parameters as a string. It's wrong. Spring JPA works fine with Date.
// Repository
List<Order> findByUserAndCreatedAtBetween(User user, Date today, String Date sevenDaysBefore);
// Service
public List<Order> getLastSevenDaysOrders(User user, Date today, Date sevenDaysBefore) {
return orderRepository.findByUserAndCreatedAtBetween(user, today, sevenDaysBefore);
}
And then
Calendar calendar = Calendar.getInstance();
Date today = calendar.getTime();
calendar.add(Calendar.DAY_OF_MONTH, -7);
Date sevenDaysBefore = calendar.getTime();
User user = userService.getUser(request.getLong("user_id"));
orders = orderService.getLastSevenDaysOrders(user, today, sevenDaysBefore);

createalias in hibernate is joining parent table two times

I have bidirectional one to many between department and employees.ie one department can have multiple employees.
I want to join department and employees using hibernate criteria so for that i am using createalias method.
Criteria criteriaDepartment = session.createCriteria(DepartmentEntity.class);
criteriaDepartment.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
criteriaDepartment.createAlias("employeeEntity", "emp",JoinType.LEFT_OUTER_JOIN);
List<DepartmentEntity> list = criteriaDepartment.list();
However, hibernate joins department table with employees and then again with the department table.
Query generated by hibernate is as follows:
Hibernate: select this_.id as id1_1_2_, this_.name as name2_1_2_, emp1_.deptId as deptId7_2_4_, emp1_.id as id1_2_4_, emp1_.id as id1_2_0_, emp1_.address as address2_2_0_, emp1_.deptId as deptId7_2_0_, emp1_.password as password3_2_0_, emp1_.phoneno as phoneno4_2_0_, emp1_.type as type5_2_0_, emp1_.userid as userid6_2_0_, department4_.id as id1_1_1_, department4_.name as name2_1_1_ from Department4 this_ left outer join Userdetails4 emp1_ on this_.id=emp1_.deptId left outer join Department4 department4_ on emp1_.deptId=department4_.id
Why Department table is joining multiple times??? Is there any way to prevent this. I have to use some restrictions as well.
However when i use fetchmode it works fine but with this method i am not able to use aliases.
Department class:
#Entity
#Table(name = "Department4")
public class DepartmentEntity {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
public int id;
public String name;
#OneToMany(mappedBy= "departmentEntity", cascade= CascadeType.ALL, orphanRemoval = true)
public Set<EmployeeEntity> employeeEntity = new HashSet<EmployeeEntity>();
public Set<EmployeeEntity> getEmployeeEntity() {
return employeeEntity;
}
public void setEmployeeEntity(Set<EmployeeEntity> employeeEntity) {
this.employeeEntity = employeeEntity;
}
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;
}
#Override
public String toString() {
return "DepartmentEntity [id=" + id + ", name=" + name + ", employeeEntity=" + employeeEntity + "]";
}
}
Employee class
#Entity
#Table(name="Userdetails4")
public class EmployeeEntity {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE)
private int id;
private String userid;
private String password;
private String address;
private long phoneno;
private String type;
#ManyToOne
#JoinColumn(name = "deptId")
private DepartmentEntity departmentEntity;
#OneToMany(mappedBy = "employeeEntity", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<AddressEntity> addressEntity = new HashSet<AddressEntity>();
public Set<AddressEntity> getAddressEntity() {
return addressEntity;
}
public void setAddressEntity(Set<AddressEntity> addressEntity) {
this.addressEntity = addressEntity;
}
public DepartmentEntity getDepartmentEntity() {
return departmentEntity;
}
public void setDepartmentEntity(DepartmentEntity departmentEntity) {
this.departmentEntity = departmentEntity;
}
public EmployeeEntity()
{}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public long getPhoneno() {
return phoneno;
}
public void setPhoneno(long phoneno) {
this.phoneno = phoneno;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#Override
public String toString() {
return "EmployeeEntity [id=" + id + ", userid=" + userid + ", password=" + password + ", address=" + address
+ ", phoneno=" + phoneno + ", type=" + type + "]";
}
}
Hibernate version: 5.2.1
Thanks in advance.

Unable to fetch the data from the database when tables are mapped by many to many

I am unable to fetch the users data from the database, and I also wonder how to handle the rest request in many to many cases for the same scenario.
I am using Spring Boot and Spring Data JPA. My code for the database is below:
CREATE TABLE `m3_group` (
`GROUP_ID` bigint(11) NOT NULL AUTO_INCREMENT,
`GROUP_NAME` varchar(30) DEFAULT NULL,
`GROUP_CREATED_DATE` datetime DEFAULT NULL,
`GROUP_ADMIN` varchar(14) DEFAULT NULL,
PRIMARY KEY (`GROUP_ID`)
)
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `m3_user` (
`USER_ID` bigint(11) NOT NULL AUTO_INCREMENT,
`USER_NAME` varchar(50) DEFAULT NULL,
PRIMARY KEY (`USER_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=330 DEFAULT CHARSET=utf8;
CREATE TABLE `m3_user_group` (
`GROUP_USER_ID` bigint(11) DEFAULT NULL,
`GROUP_ID` bigint(11) DEFAULT NULL,
KEY `FK1_GROUP_ID` (`GROUP_ID`),
KEY `FK2_USER_ID` (`GROUP_USER_ID`),
CONSTRAINT `FK1_GROUP_ID` FOREIGN KEY (`GROUP_ID`) REFERENCES `m3_group` (`GROUP_ID`),
CONSTRAINT `FK2_USER_ID` FOREIGN KEY (`GROUP_USER_ID`) REFERENCES `m3_user` (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
#Entity
#Table(name = "M3_USER")
public class User implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "USER_ID")
private long userId;
#NotBlank
#Column(name = "USER_NAME")
private String userName;
//many-to-many
#ManyToMany(mappedBy="listOfUsers",fetch=FetchType.EAGER)
private List<Group> listOfGroup=new ArrayList<Group>();
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<Group> getListOfGroup() {
return listOfGroup;
}
public void setListOfGroup(List<Group> listOfGroup) {
this.listOfGroup = listOfGroup;
}
}
#Entity
#Table(name="M3_GROUP")
public class Group implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="GROUP_ID")
private long groupId;
#Column(name="GROUP_NAME")
private String groupName;
#CreatedDate
#Temporal(TemporalType.TIMESTAMP)
#Column(name="GROUP_CREATED_DATE")
#JsonFormat(locale = "en-IN", shape = JsonFormat.Shape.STRING, pattern =
"yyyy-MM-dd HH:mm", timezone = "GMT+5:30")
private Date groupCreatedDate;
#Column(name="GROUP_ADMIN")
private String groupAdminMobileNumber;
//many-to-many
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(name = "M3_USER_GROUP", joinColumns = #JoinColumn(name =
"GROUP_USER_ID") , inverseJoinColumns = #JoinColumn(name = "GROUP_ID") )
private List<User> listOfUsers=new ArrayList<User>();
public long getGroupId() {
return groupId;
}
public void setGroupId(long groupId) {
this.groupId = groupId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public Date getGroupCreatedDate() {
return groupCreatedDate;
}
public void setGroupCreatedDate(Date groupCreatedDate) {
this.groupCreatedDate = groupCreatedDate;
}
public String getGroupAdminMobileNumber() {
return groupAdminMobileNumber;
}
public void setGroupAdminMobileNumber(String groupAdminMobileNumber) {
this.groupAdminMobileNumber = groupAdminMobileNumber;
}
public List<User> getListOfUsers() {
return listOfUsers;
}
public void setListOfUsers(List<User> listOfUsers) {
this.listOfUsers = listOfUsers;
}
}
#Repository
public interface GroupRepository extends JpaRepository<Group, Long> {
List<Group> findByGroupId(long groupid);
}
#RestController
public class GroupController
{
#Autowired
GroupRepository groupRepository;
#RequestMapping(value="/find/{groupId}",method=RequestMethod.POST)
public ResponseEntity<List<Group>> find(#PathVariable String groupId)
{
long id=Long.parseLong(groupId);
List<Group> group = groupRepository.findByGroupId(id);
System.out.println(group.toString());
return new ResponseEntity<List<Group>>(group,HttpStatus.OK);
}
}
I have mapped the user and group table with many to many bidirectional and i am trying to fetch the data i.e users associated with the groupId but listOfUsers is showing empty.
My rest request is:
Http ://localhost:5000/find/1
And the response is:
[
{
"groupId": 1,
"groupName": "Om namo raghavendra",
"groupCreatedDate": "2017-05-17 12:48",
"groupAdminMobileNumber": "917676060664",
"listOfUsers":[
]
}
]
listOfUsers is empty, so I want to users by using groupId.

Resources