I have two entities- User and Notes. One User can have multiple Notes. I am trying to implement a soft delete for both the tables. For the User table, it is working fine but for Notes table, calling deleteById is not changing the value of the deleted column to true. I tried returning findById(notesId) and it's returning right row but delete is not working.
package com.we.springmvcboot.Model;
import java.util.ArrayList;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import antlr.collections.List;
#Entity
#Table(name="User")
#SQLDelete(sql = "Update User set deleted = 'true' where UserID=?")
#Where(clause = "deleted = 'false'")//FALSE
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long UserID;
#Column(name="emailid")
private String emailID;
#Column(name="deleted")
private String deleted="false";
#OneToMany(mappedBy="user", fetch = FetchType.EAGER,cascade=CascadeType.ALL, orphanRemoval=true)
private Set<Notes> usernotes;
public User() {}
public User(String emailID) {
super();
this.emailID = emailID;
}
public String getDeleted() {
return deleted;
}
public void setDeleted(String deleted) {
this.deleted = deleted;
}
public long getUserID() {
return UserID;
}
public void setUserID(long userID) {
UserID = userID;
}
public String getemailID() {
return emailID;
}
public void setemailID(String emailID) {
this.emailID = emailID;
}
public Set<Notes> getUsernotes() {
return usernotes;
}
public void setUsernotes(Set<Notes> usernotes) {
this.usernotes = usernotes;
}
}
package com.we.springmvcboot.Model;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(name="Notes")
#SQLDelete(sql = "Update Notes set deleted = 'true' where NotesID = ?")
#Where(clause = "deleted = 'false'")
public class Notes {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long NotesID;
#Column(name="title")
private String title;
#Column(name="message")
private String message;
#Column(name="date")
private String date;
#Column(name="deleted")
private String deleted="false";
#Column(name="label")
private int label=1;
#ManyToOne()
#JoinColumn(name = "UserID", nullable = false)
private User user;
public Notes() {}
public Notes(String title, String message, String date, User user, int label) {
super();
this.title = title;
this.message = message;
this.date = date;
this.user = user;
this.label=label;
}
public Notes(long notesID, String title, String message, String date, int label) {
super();
NotesID = notesID;
this.title = title;
this.message = message;
this.date = date;
this.label=label;
}
public String getDeleted() {
return deleted;
}
public void setDeleted(String deleted) {
this.deleted = deleted;
}
public int getLabel() {
return label;
}
public void setLabel(int label) {
this.label = label;
}
public long getNotesID() {
return NotesID;
}
public void setNotesID(long notesID) {
NotesID = notesID;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public void setUser(User user) {
this.user = user;
}
}
package com.we.springmvcboot.Service;
import com.we.springmvcboot.Model.*;
import com.we.springmvcboot.exception.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import com.we.springmvcboot.Repository.NotesRepository;
import com.we.springmvcboot.Repository.UserRepository;
#Service
public class TodoService {
#Autowired
UserRepository userrepo;
#Autowired
NotesRepository notesrepo;
public Object deleteNote(Map<String, Object> input) throws InvalidInputException, NoteNotFoundException {
long userID;
try {
userID = ((Number) input.get("userID")).longValue();
} catch (Exception e) {
throw new InvalidInputException("Missing UserID");
}
HashMap<String, Object> map = new HashMap<>();
long notesID = ((Number) input.get("notesID")).longValue();
System.out.println(notesID);
if (!notesrepo.findById(notesID).isPresent())
throw new NoteNotFoundException("Invalid Notes ID");
**notesrepo.deleteById(notesID);**
map.put("status", 200);
map.put("message", "Request Successful");
map.put("data", null);
return map;
}
public Object deleteUser(Map<String, Object> input) throws NoteNotFoundException {
HashMap<String, Object> map = new HashMap<>();
long userID;
userID = ((Number) input.get("userID")).longValue();
if (!userrepo.findById(userID).isPresent())
throw new NoteNotFoundException("Invalid User ID");
userrepo.deleteById(userID);
map.put("status", 200);
map.put("message", "Request Successful");
map.put("data", null);
return map;
}
}
Try with #NamedQuery instead of #SQLDelete
or
try with
repo.deleteInBatch(list)
Related
I've done a few changes on my code, because now I want to have a soft deletion instead of a normal one.
I would only need a few JPA annotations for this purpose.
I think I got the right idea, but now I can't even run it because it give the following error:
"""Type mismatch: cannot convert from String to Class<?>"""
My CloudProduct.java ( the one with the error ) :
package com.proj.my.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.Id;
import java.sql.Date;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.Table;
#Entity
#Table(name="cloud_product_info")
#SQLDelete(sql = "UPDATE cloud_products_info SET deleted = true WHERE id=?")
#FilterDef(name = "deletedProductFilter", parameters = #ParamDef(name = "isDeleted", type = "boolean"))
#Filter(name = "deletedProductFilter", condition = "deleted = :isDeleted")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties(value = {"createdAt", "updatedAt"},
allowGetters = true)
public class CloudProduct {
#Id
private String productId;
private String productName;
private String productPrice;
#CreationTimestamp
#Column(updatable = false, name = "created_at")
private Date createdAt;
private boolean deleted = Boolean.FALSE;
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public CloudProduct(String productId, String productName, String productPrice, Date createdAt, boolean deleted) {
this.productId = productId;
this.productName = productName;
this.productPrice = productPrice;
this.createdAt = createdAt;
this.deleted = deleted;
}
public CloudProduct() {
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getProductPrice() {
return productPrice;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
}
The error is implicit on :
#FilterDef(name = "deletedProductFilter", parameters = #ParamDef(name = "isDeleted", type = "boolean"))
Specifically on the "type = "boolean" ".
He is my CloudProductController.java
package com.proj.my.controller;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.proj.my.model.CloudProduct;
import com.proj.my.service.CloudProductService;
#RestController
#RequestMapping("/cloudproduct")
public class CloudProductController
{
CloudProductService cloudProductService;
public CloudProductController(CloudProductService cloudProductService)
{
this.cloudProductService = cloudProductService;
}
#GetMapping("{productId}")
public CloudProduct getCloudProductDetails(#PathVariable("productId") String productId){
return cloudProductService.getCloudProduct(productId);
}
#PostMapping
public String createCloudProductDetails(#RequestBody CloudProduct cloudProduct){
cloudProductService.createCloudProduct(cloudProduct);
return "Success";
}
#PutMapping
public String updateCloudProductDetails(#RequestBody CloudProduct cloudProduct){
cloudProductService.updateCloudProduct(cloudProduct);
return "Updated !";
}
#DeleteMapping("/{productId}")
public void removeOne(#PathVariable("productId") String productId) {
cloudProductService.remove(productId);
}
#GetMapping
public Iterable<CloudProduct> findAll(#RequestParam(value = "isDeleted", required = false, defaultValue = "false") boolean isDeleted) {
return cloudProductService.findAll(isDeleted);
}
}
My CloudProductService.java :
package com.proj.my.service;
import com.proj.my.model.CloudProduct;
public interface CloudProductService {
public String createCloudProduct(CloudProduct cloudProduct);
public String updateCloudProduct(CloudProduct cloudProduct);
public CloudProduct getCloudProduct(String cloudProductId);
public Iterable<CloudProduct> findAll(boolean isDeleted);
public void remove(String cloudProductId);
}
My CloudProductServiceimpl.java :
package com.proj.my.service.impl;
import org.hibernate.Filter;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.proj.my.model.CloudProduct;
import com.proj.my.repository.CloudProductRepository;
import com.proj.my.service.CloudProductService;
import jakarta.persistence.EntityManager;
#Service
public class CloudProductServiceImpl implements CloudProductService
{
CloudProductRepository cloudProductRepository;
#Autowired
private EntityManager entityManager;
public CloudProductServiceImpl(CloudProductRepository cloudProductRepository) {
this.cloudProductRepository = cloudProductRepository;
}
#Override
public String createCloudProduct(CloudProduct cloudProduct){
cloudProductRepository.save(cloudProduct);
return "Success";
}
#Override
public String updateCloudProduct(CloudProduct cloudProduct){
cloudProductRepository.save(cloudProduct);
return "Success";
}
#Override
public CloudProduct getCloudProduct(String cloudProductId){
return cloudProductRepository.findById(cloudProductId).get();
}
public void remove(String cloudProductId){
cloudProductRepository.deleteById(cloudProductId);
}
public Iterable<CloudProduct> findAll(boolean isDeleted){
Session session = entityManager.unwrap(Session.class);
Filter filter = session.enableFilter("deletedProductFilter");
filter.setParameter("isDeleted", isDeleted);
Iterable<CloudProduct> products = cloudProductRepository.findAll();
session.disableFilter("deletedProductFilter");
return products;
}
}
I hope you can help me with this one, THANKS !!!
I tried to add One To Many Annotation to my spring boot project, but when I run my project I get "Failed to execute CommandLineRunner " error.
I wanted users in the user's table to have more than one city. So, I tried to add OneToMany Annotation.
You can see the error at the attachment.
User Class
package io.javabrains.springsecurity.jpa.models;
import com.spring.weather.*;
import java.util.*;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="app_user")
public class User {
#Id
#GeneratedValue(strategy =GenerationType.AUTO)
private int id;
private String userName;
private String password;
private boolean active;
private String role;
private String city;
#OneToMany(targetEntity = UserCity.class,cascade = CascadeType.ALL)
#JoinTable(name="USER_CITY",joinColumns=#JoinColumn(name="m_user_id"),
inverseJoinColumns=#JoinColumn(name="cityId"))
private List<UserCity> usercity;
public User() {
super();
// TODO Auto-generated constructor stub
}
public List<UserCity> getUsercity() {
return usercity;
}
public void setUsercity(List<UserCity> usercity) {
this.usercity = usercity;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = 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;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
User City Class
package io.javabrains.springsecurity.jpa.models;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="user_city")
public class UserCity {
#Id
#GeneratedValue(strategy =GenerationType.AUTO)
private int cityId;
private String cityName;
public UserCity() {
super();
// TODO Auto-generated constructor stub
}
public UserCity(int cityId, String cityName, User mUser) {
super();
this.cityId = cityId;
this.cityName = cityName;
this.mUser = mUser;
}
#ManyToOne
private User mUser;
public int getCityId() {
return cityId;
}
public void setCityId(int cityId) {
this.cityId = cityId;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public User getmUser() {
return mUser;
}
public void setmUser(User mUser) {
this.mUser = mUser;
}
}
User Repository
package io.javabrains.springsecurity.jpa;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import io.javabrains.springsecurity.jpa.models.User;
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUserName(String userName);
}
User City Repository
package io.javabrains.springsecurity.jpa;
import org.springframework.data.jpa.repository.JpaRepository;
import io.javabrains.springsecurity.jpa.models.User;
import io.javabrains.springsecurity.jpa.models.UserCity;
public interface CityRepository extends JpaRepository<UserCity,id>{
}
Spring Application Class
package io.javabrains.springsecurity.jpa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.spring.weather.WeatherService;
import io.javabrains.springsecurity.jpa.models.User;
import io.javabrains.springsecurity.jpa.models.UserCity;
#SpringBootApplication
#EnableJpaRepositories(basePackageClasses = UserRepository.class)
public class SpringsecurityApplication implements CommandLineRunner{
#Bean
public WeatherService ws() {
return new WeatherService ();
}
#Autowired
UserRepository userRepository;
CityRepository cityRepository;
public static void main(String[] args) {
SpringApplication.run(SpringsecurityApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
System.out.println("Application Running.");
User adminUser= new User();
UserCity ucity=new UserCity();
UserCity ucity2=new UserCity();
ucity.setCityName("amsterdam");
adminUser.setUserName("Admin");
adminUser.setPassword(new BCryptPasswordEncoder().encode("pass"));
adminUser.setRole("ROLE_ADMIN");
adminUser.setActive(true);
adminUser.setCity("bologna");
ucity.setmUser(adminUser);
userRepository.save(adminUser);
cityRepository.save(ucity);
User newUser= new User();
newUser.setUserName("User");
newUser.setPassword(new BCryptPasswordEncoder().encode("pass"));
newUser.setRole("ROLE_USER");
newUser.setActive(true);
newUser.setCity("maribor");
ucity2.setmUser(newUser);
userRepository.save(newUser);
cityRepository.save(ucity2);
}
}
The problem you are encountering, more specifically the NullPointerException at line 54 of your main application, is caused by the fact that the cityRepository is not
instantiated.
Looking through your configuration, I see that you only register the UserRepository with the #EnableJpaRepositories annotation.
Try adding also the CityRepository to the #EnableJpaRepositories, and also specify this bean as a candidate for autowiring( also add #Autowired to this bean, as you did for UserRepository)
For a good practice, following the MVC structure, it would be nice is all your spring repositories, the beans responsible for all CRUD operations with the database to be under the same package
Started learning Spring Boot, JPA. Finding difficult on understanding JPA relationship concepts, I tried joining two tables but could not achieve the expected result can anyone help me to get the expected result.
Below Requirement
Have two tables as below
product_master table
product_catagory table
ProductMasterModel
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "product_master")
public class ProductMasterModel {
#Id
#GeneratedValue
#Column(name = "product_id")
private int productId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_category_id")
private int productCategoryId;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "product_category_id", referencedColumnName = "product_catogory_id",insertable = false, updatable = false)
private ProductCatagoryMasterModel productCatagoryMasterModel;
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getProductCategoryId() {
return productCategoryId;
}
public void setProductCategoryId(int productCategoryId) {
this.productCategoryId = productCategoryId;
}
public ProductMasterModel() {
super();
}
public ProductMasterModel(String productName, int productCategoryId) {
super();
this.productName = productName;
this.productCategoryId = productCategoryId;
}
}
ProductCatagoryMasterModel
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table (name="product_catagory")
public class ProductCatagoryMasterModel {
#Id
#GeneratedValue
#Column(name="product_catogory_id")
private int productCategoryId;
#Column(name="product_type")
private String productType;
#OneToOne(mappedBy = "productCatagoryMasterModel")
private ProductMasterModel productMasterModel;
public int getProductCategoryId() {
return productCategoryId;
}
public void setProductCategoryId(int productCategoryId) {
this.productCategoryId = productCategoryId;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public ProductCatagoryMasterModel() {
super();
}
public ProductCatagoryMasterModel(String productType) {
super();
this.productType = productType;
}
}
ProductMasterRepository
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.lollipop.model.ProductMasterModel;
#Repository
public interface ProductMasterRepository extends CrudRepository<ProductMasterModel, Integer> {
#Query (value = "select * from product_master pm, product_catagory pc where pc.product_catogory_id = pm.product_category_id", nativeQuery = true)
public List $ProductMasterModel$ getProductCategoryDetail();
}
ProductService
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lollipop.model.ProductMasterModel;
import com.lollipop.repository.ProductMasterRepository;
#Service
#Transactional
public class ProductService {
#Autowired
private ProductMasterRepository productMasterRepository;
public void getProductCat() {
List $ProductMasterModel$ productMasterModel = productMasterRepository.getProductCategoryDetail();
System.out.println("productMasterModel value "+productMasterModel.toString());
}
}
When calling getProductCat() method getting result as
productMasterModel value [ProductMasterModel [productId=1011,
productName=Pencil, productCategoryId=10], ProductMasterModel
[productId=1012, productName= Mobile, productCategoryId=11]]
Since ProductMasterModel is not having productType variable it is not displaying productType
I need below result by joining two tables, please help me to acheive this
[[productName=Pencil,productType=Stationary],[productName=
Mobile,productType=Electronics]]
Yes, One to One Relationship should work.
Changes should be made in your POJO.
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "product_master")
public class ProductMasterModel {
#Id
#GeneratedValue
#Column(name = "product_id")
private int productId;
#Column(name = "product_name")
private String productName;
#Column(name = "product_category_id")
private int productCategoryId;
#OneToOne(mappedBy= product_master, fetch = FetchType.LAZY)
public ProductCatagoryMasterModel productCatagory;
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public int getProductCategoryId() {
return productCategoryId;
}
public void setProductCategoryId(int productCategoryId) {
this.productCategoryId = productCategoryId;
}
public ProductMasterModel() {
}
public ProductMasterModel(String productName, int productCategoryId) {
super();
this.productName = productName;
this.productCategoryId = productCategoryId;
}
}
Next Address your Category Model
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table (name="product_catagory")
public class ProductCatagoryMasterModel {
#Id
#GeneratedValue
#Column(name="product_catogory_id")
private int productCategoryId;
#Column(name="product_type")
private String productType;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "product_master", referencedColumnName = "product_id")
private ProductMasterModel productMaster;
public int getProductCategoryId() {
return productCategoryId;
}
public void setProductCategoryId(int productCategoryId) {
this.productCategoryId = productCategoryId;
}
public String getProductType() {
return productType;
}
public void setProductType(String productType) {
this.productType = productType;
}
public ProductCatagoryMasterModel() {
super();
}
public ProductCatagoryMasterModel(String productType) {
super();
this.productType = productType;
}
}
We also need DAO
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.lollipop.model.ProductMasterModel;
#Repository
public interface ProductMasterRepository extends CrudRepository<ProductMasterModel, Integer> {
}
Product Service
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lollipop.model.ProductMasterModel;
import com.lollipop.repository.ProductMasterRepository;
#Service
#Transactional
public class ProductService {
#Autowired
private ProductMasterRepository productMasterRepository;
public List<ProductMasterModel > getAllProducts() {
return productMasterRepository.findAll();
}
public Optional<ProductMasterModel > getProductById(int productId) {
if (!productMasterRepository.existsById(productId)) {
throw new ResourceNotFoundException("Product with id " + productId+ " not found");
}
return productMasterRepository.findById(productId);
}
}
}
You need to establish ont-to-one relationship between those two tables.
Take a look at this:
Example
I'm creating a dynamic menu using spring and hibernate based on user roles. It works fine and menu is getting generated. but the relationship between menu and submenu doesn't work properly. I want only submenus which has roles assigned to them. but it contains all the submenus.
My POJOs are like below.
Menu.java
package com.pmc.domain;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.Fetch;
#Entity
#Table(name="menu", catalog="test")
public class Menu implements Serializable{
#Id
#Column(name = "menu_item_id")
private Integer menuId;
#ManyToMany(cascade={CascadeType.ALL})
#JoinTable(name="MENU_ROLES",
joinColumns={#JoinColumn(name="menu_item_id")},
inverseJoinColumns={#JoinColumn(name="user_role_id")})
private List<UserRole> userRoles;
#Column(name = "label", length = 100)
private String label;
#Column(name = "link", length = 100)
private String link;
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name = "parent")
private Menu parent;
#OneToMany(mappedBy="parent",fetch = FetchType.EAGER)
private List<Menu> submenus;
public Integer getMenuId() {
return menuId;
}
public void setMenuId(Integer menuId) {
this.menuId = menuId;
}
public List<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(List<UserRole> userRoles) {
this.userRoles = userRoles;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public Menu getParent() {
return parent;
}
public void setParent(Menu parent) {
this.parent = parent;
}
public List<Menu> getSubmenus() {
return submenus;
}
public void setSubmenus(List<Menu> submenus) {
this.submenus = submenus;
}
}
UserRole.java
package com.pmc.domain;
import static javax.persistence.GenerationType.IDENTITY;
import java.util.List;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
#Entity
#Table (name = "roles", catalog = "test")
public class UserRole {
private Integer userRoleId;
private Set<User> users;
private String role;
private List<Menu> menus;
public UserRole() {
}
public UserRole(Set<User> users, String role) {
this.users = users;
this.role = role;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_role_id",
unique = true, nullable = false)
public Integer getUserRoleId() {
return this.userRoleId;
}
public void setUserRoleId(Integer userRoleId) {
this.userRoleId = userRoleId;
}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name="USER_ROLES",
joinColumns={#JoinColumn(name="user_role_id")},
inverseJoinColumns={#JoinColumn(name="username")})
public Set<User> getUsers() {
return this.users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
#Column(name = "role", nullable = false, length = 45)
public String getRole() {
return this.role;
}
public void setRole(String role) {
this.role = role;
}
#ManyToMany(mappedBy="userRoles",fetch = FetchType.EAGER)
public List<Menu> getMenus() {
return menus;
}
public void setMenus(List<Menu> menus) {
this.menus = menus;
}
}
User.java
package com.pmc.domain;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="users", catalog="test")
public class User {
private String username;
private String password;
private boolean enabled;
private Set<UserRole> userRole = new HashSet<UserRole>(0);
public User() {
}
public User(String username, String password, boolean enabled) {
this.username = username;
this.password = password;
this.enabled = enabled;
}
public User(String username, String password,
boolean enabled, Set<UserRole> userRole) {
this.username = username;
this.password = password;
this.enabled = enabled;
this.userRole = userRole;
}
#Id
#Column(name = "username", unique = true,
nullable = false, length = 45)
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password",
nullable = false, length = 60)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name = "enabled", nullable = false)
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
#ManyToMany(mappedBy = "users")
public Set<UserRole> getUserRole() {
return this.userRole;
}
public void setUserRole(Set<UserRole> userRole) {
this.userRole = userRole;
}
}
my query is like this.
select menu from User user, IN (user.userRole) roles, IN(roles.menus) menu where user.username = ?
It gives all the required menus with proper roles to the user. But the list of submenus in each menu is not reflected according to the roles.
Can you please help on this?
Thanks
I am new to Hibernate and I am trying to understand the oneToMany concept. I have created two entities which are Person and Book. A person can borrow many books and a book can only have one person borrowing it. So I have made the following classes
Person.java
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Entity
#Table(name="PERSON")
public class Person {
private static final Logger _logger = LoggerFactory.getLogger(Person.class);
#Id
#GenericGenerator(name="adder", strategy="increment")
#GeneratedValue(generator="adder")
#Column(name="PID")
private Long id;
#Column(name="FIRSTNAME")
private String firstName;
#Column(name="LASTNAME")
private String lastName;
#Column(name="BIRTHDATE")
#Temporal(TemporalType.DATE)
private Date birthDate;
//add genre and books
#OneToMany(orphanRemoval=true, mappedBy="person", cascade=CascadeType.ALL,targetEntity=Book.class)
private Set<Book> listOfBooks = new HashSet<Book>();
public Set<Book> getListOfBooks() {
return listOfBooks;
}
public void setListOfBooks(Set<Book> listOfBooks) {
this.listOfBooks = listOfBooks;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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 Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
//add constructor with all the details
}
Book.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#Entity
#Table(name="BOOK")
public class Book {
private static final Logger logger = LoggerFactory.getLogger(Book.class);
#Id
#GenericGenerator(name="adder", strategy="increment")
#GeneratedValue(generator="adder")
private Long bookId;
#Column(name="NAME")
private String name;
#Column(name="AUTHOR")
private String author;
#Column(name="PUBLICATION_YEAR")
private int yearOfPublication;
#Column(name="PUBLISHER")
private String publisher;
#ManyToOne()
#JoinColumn(name="PERSON_ID")
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public int getYearOfPublication() {
return yearOfPublication;
}
public void setYearOfPublication(int yearOfPublication) {
this.yearOfPublication = yearOfPublication;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
}
HibernateLibraryDaoMain.java
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import se325.project.assignment1.hibernate.domain.Book;
import se325.project.assignment1.hibernate.domain.Person;
public class HibernateLibraryDaoMain {
public static void main(String[] args) {
Person person = new Person();
person.setFirstName("Bob");
person.setLastName("Marley");
person.setBirthDate(new Date());
Book book = new Book();
book.setName("Bob Marley book");
book.setAuthor("Lily Marley");
book.setPublisher("Marley Publications");
book.setYearOfPublication(2000);
Book book1 = new Book();
book1.setName("Laura Marley book");
book1.setAuthor("Laura Marley");
book1.setPublisher("Laura Publications");
book1.setYearOfPublication(2005);
person.getListOfBooks().add(book);
person.getListOfBooks().add(book1);
book.setPerson(person);
book1.setPerson(person);
Configuration configuration = new Configuration();
configuration.configure("se325/project/assignment1/hibernate/hibernate.cfg.xml");
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties()).build();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(person);
session.save(book);
session.save(book1);
session.getTransaction().commit();
session.close();
}
}
The problem is that Hibernate does not create a separate Table that illustrates the oneToMany relationship. I can't seem to find the problem. Any help would be appreciated.
I understand where I went wrong. When I have a mappedBy property set, then Hibernate doesn't create a third table but instead it adds to the Entity that has the ManyToOne and joinColumn property. Thanks to all the users that helped :)