Cannot update a single entity in Many-to-Many relationship - java

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:)

Related

Creating association between entity to-many JPA

I want to make association to some many-to-many relation entity
#Entity
#Table(name = "users")
#Data
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private String userId;
private String name;
#OneToMany(mappedBy = "user")
private List<UserGroups> userGroups;
#Table(name = "groups")
#Data
public class Group {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id")
private String groupId;
private String category;
private String name;
private String description;
#OneToMany(mappedBy = "group")
private List<UserGroups> userGroups;
public void addUser(User user){
UserGroup newUserGroup = new UserGroup();
newUserGroup.setName(user.getName())
userGroups.add(newUserGroup);
user.getUserGroups().add(newUserGroup)
}
#Entity
#Data
#Table(name = "user_groups")
public class UserGroups {
#EmbeddedId
UserGroupsCompositeKey id;
#ManyToOne
#MapsId("userId")
#JoinColumn(name = "user_id")
private Users user;
#ManyToOne
#MapsId("featureId")
#JoinColumn(name = "group_id")
private Group group;
private Date created;
I trying to add POST method to service where I should get group_id from endpoint url and assosiate user_id in request body. My Service method looks like this.
#Override
public ResponseEntity<String> createUsersGroup(String groupId,
String userId) {
Optional<Group> group = groupRepository.findById(groupId).get();
Optional<User> user = userRepository.findById(userId).get();
group.addUser(user);
return ResponseEntity.ok(userId);
};
}
Is there some more proper way to do this or when I will add more users in request body I will have to pull out every user from the database and add it like that ?

role based creation of users in Spring boot

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.

Foreign Key is Null

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);

Spring boot data rest/jpa #JoinTable insertion

I'm creating a MySQL database as followed :
database design
the Country and Province tables are pre-filled with data. I have the application running and can get stuff no problem, and also the join table person_has_address works when getting.
however, when I insert data using post I want to be able to set the ID of the province, and let spring data jpa just add that number to add_pro_id in the Address table. For example, when I post the following json:
{ "firstName":"bilbo", "lastName":"baggings", "address":{"street":"streetName", "streetNum":3, "zipcode":"1337GG", "city":"TheCity", "province":{"name":"aProvinceName"}} }
jpa should see that aProvinceName exists and grab that id and add that to add_pro_id.
Now it just insert aProvinceName as new value in province and add the new id to add_pro_id.
The person class:
#Entity
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="per_id")
private int id;
#Column(name="per_name")
private String firstName;
#Column(name="per_surname")
private String lastName;
#Column(name="per_birth_date")
private String birthDate;
#Column(name="per_fax")
private String fax;
#Column(name="per_phone")
private String phone;
#Column(name="per_email")
private String email;
#OneToOne(optional = false, cascade = CascadeType.ALL)
#JoinTable(name="person_has_address", joinColumns = {#JoinColumn(name="pha_per_id", referencedColumnName = "per_id")}, inverseJoinColumns = {#JoinColumn(name="pha_add_id", referencedColumnName = "add_id")})
private Address address;
// getters and setters
This is the person repository:
#RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
List<Person> findByLastName(#Param("name") String name);
}
This is the address class:
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="add_id")
private int id;
#Column(name = "add_street")
private String street;
#Column(name="add_street_num")
private int streetNum;
#Column(name="add_zip")
private String zipcode;
#Column(name="add_city")
private String city;
#JoinColumn(name="add_pro_id", referencedColumnName = "pro_id")
#ManyToOne(optional=false, cascade = CascadeType.ALL)
private Province province;
// getters and setters
Province class:
#Entity
public class Province {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="pro_id")
private int id;
#Column(name="pro_name")
private String name;
#ManyToOne
#JoinColumn(name="pro_cou_id")
private Country country;
// getters and setters
And lastly country class:
#Entity
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="cou_id", insertable = false, updatable = false)
private int id;
#Column(name="cou_name", insertable = false, updatable = false)
private String name;
// getters and setters
I've tried adding insertable = false and updatable = false, but the application then just inserts NULL values in my database. I've also tried working with #primarykeyjoins, but to no success.
if anyone knows how I should tackle this problem I would much appreciate it!
Thanks in advance.

Retrieve logged user object and save it as a foreign key

While saving some data from the form I also need to add FK to the Record table. FK is User.Id.
I know how to save data from the input field on the form, but how can I set FK (int value) to this:
#ManyToOne
#JoinColumn(name = "id")
#Cascade({CascadeType.ALL})
private User user;
Is there some way to retrieve object which relates to logged user and make something like this: record.setUser(user)?
I've googled it but I didn't manage to find how to achive this.
This is my entity class.
#Entity
public class Record implements java.io.Serializable{
#Id
#GeneratedValue
private int recordId;
private String recordName;
private String recordComment;
private Date recordDate;
private Integer price;
#ManyToOne
#JoinColumn(name = "userId", insertable = true, updatable = false)
#Cascade({CascadeType.ALL})
private User user;
......
}
#Entity
#Table(name = "system_user")
public class User implements java.io.Serializable{
#Id
#GeneratedValue
private int userId;
#NotEmpty
#Email
private String email;
#Size(min=2, max=30)
private String name;
private String enabled;
#NotEmpty
private String password;
private String confirmPassword;
#Enumerated(EnumType.STRING)
#Column(name = "user_role")
private Role role;
#OneToMany(fetch = FetchType.EAGER,mappedBy = "user", orphanRemoval=true)
#Cascade({CascadeType.ALL})
private List<Record> records;
public void addToRecord(Record record) {
record.setUser(this);
this.records.add(record);
}
....
}
This is how I save data to DB:
#RequestMapping(value = "/protected/add", method = RequestMethod.POST)
public String addCost (#ModelAttribute("record") Record record,HttpSession session){
User user = userManager.getUserObject(userManager.getUserId(session.getAttribute("currentUser").toString()));
user.addToRecord(record);
recordService.addRecord(record);
return "redirect:/protected/purse";
}
DAO:
public void addRecord(Record record) {
sessionFactory.getCurrentSession().save(record);
}
UPDATE: problem was partially solved, code above works fine for me.
You also need to create User object and set the user object in a Record object using the below code
record.setUser(userObj);
and user foreign key will be automatically saved in database.

Categories