I trying to make relation between phonebook and user through jpa, when the current logged in user creates a contact the foreign key of user in table phonebook remains null. I checked couple of question here but it did'not work for me.
Phonebook
#Entity
#Table(name = "Phonebook")
public class Phonebook {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "phonebook_id")
private Long id;
#Column(name = "phone", length = 15, nullable = false)
private String phoneNumber;
#Column(name = "firstname", length = 50, nullable = false)
private String firstName;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
//getters and setters
User
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long id;
#Column(name = "email")
private String email;
#Column(name = "password")
#Length(min = 5, message = "*Your password must have at least 5 characters")
#org.springframework.data.annotation.Transient
private String password;
#OneToMany(mappedBy = "user")
private List<Phonebook> phonebooks;
//getters and setters
PhonebookController
#RequestMapping(value = {"/home/phonebook"}, method = RequestMethod.GET)
public String showPage(Model model, #RequestParam(defaultValue = "0") int page){
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = userService.findUserByEmail(auth.getName());
model.addAttribute("data",phonebookRepository.findAllByUserId(user.getId(),PageRequest.of(page,10)));
model.addAttribute("currentPage",page);
return "/home/phonebook";
}
#PostMapping("/home/phonebook/save")
public String save (Phonebook p){
phonebookRepository.save(p);
return "redirect:/home/phonebook";
}
PhonebookRepository
#Repository("phonebookRepository")
public interface PhonebookRepository extends JpaRepository<Phonebook,Integer> {
List<Phonebook> findAllByUserId(Long id, Pageable pageable);
}
what You have to do the first create a user object and set the id and then persist the phone book.
You must persist PhoneBook together with your User.
User u = new User();
// Set properties for your User...
PhoneBook p = new PhoneBook();
// Set properties for your phonebook...
// Store phone book to user:
u.setPhoneBook(Collections.singletonList(p));
userRepository.save(p);
Related
I am currently making project which should have Many-To-Many relationship between groups and users. I should be able to update an user and add one. I have no troubles with adding an user, it gets saved properly. However, when I try to update user, it gives an error that definitely has something to do with that hibernate tries to save groups information. Here is my code.
User Entity
#Entity
#Table(name = "user")
public class User {
#Id
#Column(name = "email")
private String email;
#Column(name = "firstname")
private String name;
#Column(name = "lastname")
private String surname;
#Column(name = "age")
private int age;
#Column(name = "gender")
private String gender;
#ManyToMany
#JoinTable(
name = "user_group"
, joinColumns = #JoinColumn(name = "email")
, inverseJoinColumns = #JoinColumn(name = "group_id")
)
Group entity
#Entity
#Table(name = "category")
public class Group {
#Id
#Column(name = "group_name")
private String name;
#Column(name = "description")
private String description;
#ManyToMany(mappedBy = "groupList")
private List<User> userList = new ArrayList<User>();
Controller save method
#PostMapping("/addUser")
public String addUser(#ModelAttribute("user") User user) {
service.saveUser(user);
return "redirect:/allUsers";
}
Service save method
#Override
#Transactional
public void saveUser(User user) {
userDAO.saveUser(user);
}
DAO save method
#Override
public void saveUser(User user) {
entityManager.merge(user);
}
java.sql.SQLSyntaxErrorException: Unknown column 'group1_.description' in 'field list
The problem was that I altered my column names in DB but forgot to update it in Entity class. Got to be careful next time:)
Here I m having two different tables, User and Profile Image. Both are mapped using One to One relation. The problem is- Foreign key of Profile Image (user_userid) is null when a new profile image is inserted into the database. Why is the user_id remains null... I come up with this issue many time.... Is there any issue with the way I m mapping both the entities?...
User
#Entity
#Getter
#Setter
#Table(name = "Users")
public class User {
#Id
#Column(name = "user_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#OneToOne(cascade = CascadeType.ALL,mappedBy = "user",fetch =FetchType.LAZY)
private UserProfileImage userProfileImage;
}
Profile Image
#Entity
#Getter
#Setter
public class UserProfileImage {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "name")
private String name;
#Column(name = "type")
private String type;
#Column(name = "picByte", length = 1000000)
private byte[] picByte;
#OneToOne(fetch =FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
public UserProfileImage() {
super();
}
public UserProfileImage(String name, String type, byte[] picByte) {
this.name = name;
this.type = type;
this.picByte = picByte;
}
}
Controller
public ResponseEntity<String> addProfileImage(int id,MultipartFile file) {
User user=userRepository.findById(id);
UserProfileImage present=user.getUserProfileImage();
if(present==null) {
UserProfileImage userProfileImage = new UserProfileImage(file.getOriginalFilename(), file.getContentType(), file.getBytes());
user.setUserProfileImage(userProfileImage);
}else{
present.setName(file.getOriginalFilename());
present.setType(file.getContentType());
present.setPicByte(file.getBytes());
user.setUserProfileImage(present);
}
userRepository.save(user);
}
As it's stated in the hibernate documentation:
Whenever a bidirectional association is formed, the application developer must make sure both sides are in-sync at all times.
So, you should correct your addProfileImage method in this way:
public ResponseEntity<String> addProfileImage(int id,MultipartFile file) {
User user=userRepository.findById(id);
UserProfileImage present=user.getUserProfileImage();
if(present==null) {
UserProfileImage userProfileImage = new UserProfileImage(file.getOriginalFilename(), file.getContentType(), file.getBytes());
// sync both sides of bidirectional association
user.setUserProfileImage(userProfileImage);
userProfileImage.setUser(user);
} else {
present.setName(file.getOriginalFilename());
present.setType(file.getContentType());
present.setPicByte(file.getBytes());
// this is redundant
// user.setUserProfileImage(present);
}
userRepository.save(user);
}
i have Three entities User, Institution and Role.
1)one to many between user and institution
2)and many to many between User and Role
-------user-------
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="user_Id")
private int userId;
#Column(name="name")
private String name;
#Column(name="lastname")
private String lastname;
#Column(name="email")
private String email;
#Column(name="password")
private String password;
#Column(name="isActive")
private boolean isActive;
#Column(name="lastActive")
private String lastActive;
#Column(name="createdDate")
private String createdDate;
#Column(name="isBlocked")
private boolean isBlocked;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "institution_id", nullable = false)
#JsonIgnoreProperties(value = {"user"})
private Institution institution;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "user_has_role",
joinColumns = {
#JoinColumn(name = "user_id", referencedColumnName = "user_id",
nullable = false, updatable = true)},
inverseJoinColumns = {
#JoinColumn(name = "role_id", referencedColumnName = "role_id",
nullable = false, updatable = true)})
#JsonIgnoreProperties(value = {"users"})
private Set<Role> roles = new HashSet<>();
}
-------institution-------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "institution")
public class Institution {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="institution_Id")
private int institutionId;
#Column(name="name")
private String name;
#Column(name="type")
private String type;
#Column(name="location")
private String location;
#OneToMany(mappedBy = "institution", fetch = FetchType.LAZY)
#JsonIgnoreProperties(value = {"institution" , "user"})
private Set<User> user;
}
-------role-------
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="role_Id")
private int roleId;
#Column(name="name")
private String name;
#Column(name="description")
private String description;
#ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
#JsonIgnoreProperties(value = {"roles"})
private Set<User> users = new HashSet<>();
}
Those are my 3 entities and tables in MySql
i have 7 roles
• Super-User
• Bank-Admin
• Bank-Support
• Bank-Service
• Merchant-Admin
• Merchant-Support
• Merchant-service
The super-User can create a user of any role
#PostMapping("/addUser")
public String addUser(#RequestBody User user) {
String rawpassword = user.getPassword();
String encodedpasswrod = passwordencoder.encode(rawpassword);
user.setPassword(encodedpasswrod);
userrepository.save(user);
return "user saved with name: " + user.getName();
}
this api works and i can set the role to anything in my api json body
But want that if the User is Bank-Admin he can only create Bank-Support and Bank-Service
im trying to create a new API which can only create a user with those 2 specific roles.
and then restrict the bank admin to access the other API that can create users of any kind.
is there any other way to do it and if no how can i do that...
You have to implement your custom implementation of User Entitlement.
Like according to login person, you will get that login person role, and according to your criteria just put validation like check that entity he is trying to add is he eligible to create it.
Map<String, List<String>> roleUserAccessMap = new HashMap<>();
roleUserAccessMap.put("Bank-Admin", Arrays.asList("Bank-Support", "Bank-Service"));
Just check like below
String loginPersonRole="Bank-Admin"; //This value should get from logged-in person context
if(roleUserAccessMap.containsKey(loginPersonRole) && roleUserAccessMap.get(loginPersonRole).contains(newuserrole) ){
//proceed ahead with Add api
}else{
System.out.println("You do not have enough privileage to create Use");
}
This will help you.
For the current structure of database:
database structure
Users
#Entity
#Table(name = "users")
public class User {
#Id
#Column(name = "username", unique = true, nullable = false, length = 45)
private String username;
#Column(name = "password", nullable = false, length = 60)
private String password;
#Column(name = "enabled", nullable = false)
private boolean enabled;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade=CascadeType.ALL)
private Set<UserRole> userRole = new HashSet<UserRole>(0);
#ManyToMany(fetch=FetchType.EAGER)
#JoinTable(
name = "users_product",
joinColumns ={#JoinColumn (name = "users_username", referencedColumnName = "username")},
inverseJoinColumns = {#JoinColumn(name = "Products_idProducts", referencedColumnName = "idProducts")}
)
List<Products> productsList = new ArrayList<Products>();
Products
#Entity
#Table(name = "products")
public class Products implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "idProducts")
private long id;
#Column(name = "description")
private String description;
#Column(name = "price")
private String price;
#Column(name = "image")
private byte [] image;
#ManyToMany(mappedBy = "productsList")
List<User> usersList = new ArrayList<User>();
//setters - getters
I want to implement a shopping basket.
What I have now: A page with products and checkboxes on the view page. I find these products and send them to my controller, and afterwards set them to the current user.
productsList = myService.findManyProducts(toAdd);
user.setProductsList(productsList);
myService.updateUser(user);
#Transactional
public void updateUser(User user){
userDao.update(user);
}
update user function:
#Override
public void update(User user) {
entityManager.merge(user);
}
These actions are entered in the database as different values, depending on the latest additions.
What I want:
User adds some products to cart, browse other items, and add new products to the cart. How do I ensure that duplicate items are not found in the cart? Does JPA have some standard methods? Or do I need to check the product list by myself before adding them to the database?
I solved this by changing the List collection to a Set in the User entity.
I have three tables
employee: storing employee information
role_description: storing types of role i have like admin, zone manger, country manager
employee_role_details: having many to many relationship from employee and role description with some extra fields.
Now I am facing an issue in fetching result that contains (employee_id, email) from employee table, (role_ownership, role_id) from employee_role_details and (role_name and role_description)from role_description corresponding to role_id in role_description.
Employee.java
#Entity
#Table(name = "employee", uniqueConstraints= #UniqueConstraint(columnNames={"employee_email"}))
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "employee_id")
private long employeeId;
#Column(name = "employee_name")
private String employeeName;
#Column(name = "employee_email", unique = true, nullable = false)
private String employeeEmail;
#Column(name = "contact_no")
private String contactNo;
#Column(name = "password")
private String password;
#Column(name = "is_active")
private Boolean isActive = true;
#Transient
private long EmployeeRoleId;
#Transient
private String roleName;
#Transient
private int totalpage;
#OneToMany(mappedBy = "employee", cascade = CascadeType.ALL)
//#JsonIgnore
#JsonManagedReference(value = "employeeRoleRecord-employee")
#LazyCollection(LazyCollectionOption.FALSE)
private List<EmployeeRoleRecord> roleRecords = new ArrayList<>();
#OneToMany(mappedBy = "assignedTo", cascade = CascadeType.ALL)
#JsonManagedReference(value = "complaint-treatment-employee")
#LazyCollection(LazyCollectionOption.FALSE)
private List<ComplaintsCategory> complaintCategoryAssignedTo = new ArrayList<>();
EmployeeDescription.java
#Entity
#Table(name = "role_description")
public class RoleDescription {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private long roleId;
#Column(name = "role_name")
private String roleName;
#Column(name = "role_description")
private String roleDescription;
#Column(name = "status")
private boolean status;
#OneToMany(mappedBy = "description", cascade = CascadeType.ALL)
#JsonManagedReference(value = "employeeRoleRecord-roleDescription")
#LazyCollection(LazyCollectionOption.FALSE)
private List<EmployeeRoleRecord> roleRecords = new ArrayList<EmployeeRoleRecord>();
EmployeeRoleRecord
#Entity
#Table(name = "employee_role_record")
public class EmployeeRoleRecord {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "employee_role_id")
private long employeeRoleId;
#Column(name = "role_ownership")
private String roleOwnership;
#Column(name = "status")
private boolean status = true;
#ManyToOne(cascade=CascadeType.ALL)
#JsonBackReference(value = "employeeRoleRecord-employee")
#JoinColumn(name = "employee_id")
private Employee employee;
#ManyToOne(cascade=CascadeType.ALL)
#JsonBackReference(value = "employeeRoleRecord-roleDescription")
#JoinColumn(name = "role_id")
private RoleDescription description;
#Transient
private long roleId;
Code inside a dao
public Employee getEmployeeByEmail(String email) {
return (Employee) sessionFactory.getCurrentSession()
.createCriteria(Employee.class)
.add(Restrictions.eq("employeeEmail", email)).uniqueResult();
}
services:
public Employee getSurveyData(String employeeEmail){
Employee loggedInEmployee =
loginDao.getEmployeeByEmail(employeeEmail);
Employee loggedInEmployeeRecord = new Employee();
loggedInEmployeeRecord.setEmployeeId(loggedInEmployee.getEmployeeId());
loggedInEmployeeRecord.setEmployeeName(loggedInEmployee.getEmployeeName());
List<EmployeeRoleRecord> employeeRoleRecords = loggedInEmployee.getRoleRecords();
List<EmployeeRoleRecord> employeeRoleRecord = new ArrayList<>();
for(EmployeeRoleRecord record : employeeRoleRecords){
EmployeeRoleRecord employeeRole = new EmployeeRoleRecord();
employeeRole.setRoleId(record.getDescription().getRoleId());
employeeRole.setRoleName(record.getDescription().getRoleName());
employeeRole.setRoleOwnership(record.getRoleOwnership());
employeeRole.setStatus(record.isStatus());
employeeRoleRecord.add(employeeRole);
}
loggedInEmployeeRecord.setRoleRecords(employeeRoleRecord);
return loggedInEmployee;
}
Output:
{
"employeeId": 1,
"employeeName": "Dhyanandra Singh",
"employeeEmail": "admin",
"contactNo": "9893651872",
"password": "123456",
"isActive": true,
"roleRecords": [
{
"employeeRoleId": 1,
"roleOwnership": "overall project",
"status": true,
"roleId": 0,
"roleName": null
}
],
}
problem:
json output i'm getting is not containing role id and role name in role records list.
The problem is:
Your roleId attribute on EmployeeRoleRecord classe is mapped as #Transient, which means that it is not persisted on database, so Hibernate is not able to fetch the result of this field.
Looking at your classes modeling I couldn't figure out exactly what you are trying to map with the roleId, I suggest two possible approaches:
Do not return directly your query on getEmployeeByEmail method. First get the results, then iterate it and set manually the desired roleId you want on each record;
Check your model scheme and make the correct mapping for roleId, it probably should reference another entity, so make sure to map the relationship correctly to get your results on a single query.
Good luck.
added transient roleId and roleName in EmployeeRoleRecord then having some modification in services. like iterating list setting roleId and roleName in it.
public Employee getSurveyData(String employeeEmail){
Employee loggedInEmployee =
loginDao.getEmployeeByEmail(employeeEmail);
Employee loggedInEmployeeRecord = new Employee();
loggedInEmployeeRecord.setEmployeeId(loggedInEmployee.getEmployeeId());
loggedInEmployeeRecord.setEmployeeName(loggedInEmployee.getEmployeeName());
loggedInEmployeeRecord.setEmployeeEmail(loggedInEmployee.getEmployeeEmail());
loggedInEmployeeRecord.setContactNo(loggedInEmployee.getContactNo());
List<EmployeeRoleRecord> employeeRoleRecords = loggedInEmployee.getRoleRecords();
List<EmployeeRoleRecord> employeeRoleRecord = new ArrayList<>();
for(EmployeeRoleRecord record : employeeRoleRecords){
EmployeeRoleRecord employeeRole = new EmployeeRoleRecord();
employeeRole.setEmployeeRoleId(employeeRole.getEmployeeRoleId());
employeeRole.setRoleId(record.getDescription().getRoleId());
employeeRole.setRoleName(record.getDescription().getRoleName());
employeeRole.setRoleOwnership(record.getRoleOwnership());
employeeRole.setStatus(record.isStatus());
employeeRoleRecord.add(employeeRole);
}
loggedInEmployeeRecord.setRoleRecords(employeeRoleRecord);
return loggedInEmployeeRecord;
}