I have 2 entitie. User:
#Table(name = "USERS")
#Entity
public class User {
#Column(name = "user_id")
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private String email;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
private Authentication authentication;
}
and Authentication:
#Table(name = "AUTHENTICATIONS")
#Entity
public class Authentication {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "login_id")
private String loginId;//openId login
#JsonIgnore
private String password;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
}
And I have service which provides registration for new users:
#Override
#Transactional
public User createUser(UserRegistrationForm form) {
Authentication authentication = new Authentication();
authentication.setPassword(form.getPassword());
User user = new User();
user.setAuthentication(authentication);
user.setEmail(form.getEmail());
user.setName(form.getLogin());
authentication.setUser(user);
return userRepository.save(user);
}
And my problem is method userRepository.save() returns infinitely nested objects:
{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"myName","email":"myemail#gmail.com","authentication":{"id":1,"loginId":null,"user":{"id":1,"name":"
What am I doing wrong? Help to understand how it should work.
it's json which returns nested objects ... not your repository !
you are using jackson ?
add #JsonManagedReference on one side and #JsonBackReference on the other
Your problem is:
user.setAuthentication(authentication);
...
authentication.setUser(user);
You have a nested reference between user and authentication
Related
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 ?
this is my code:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER, optional = false)
private Employee employee;
public User() {
}
//SETTERS AND GETER
}
#Entity
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
public Employee() {
}
//SETTERS AND GETER
}
On my service I'm trying somthing like this:
User user = new User();
user.setUsername("my_username");
user.setPassword("12345");
Employee employee = new Employee();
employee.setName("My Name");
employee.setBirth(LocalDate.now());
user.setEmployee(employee);
userService.save(user);
There Are no errors nor any problem on the application, but looking on my database, the user_id column is empty, what is for me to do to have user_id set automatically with User id? Thanks in advance!
As it is 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.
You use bidirectional #OneToOne so, you should synchronize both side of the association:
User user = new User();
user.setUsername("my_username");
user.setPassword("12345");
Employee employee = new Employee();
employee.setName("My Name");
employee.setBirth(LocalDate.now());
// make both side of bidirectional #OneToOne in-sync
user.setEmployee(employee);
employee.setUser(user);
userService.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.
I am getting a JSON which is deserialised into a POJO and I am trying to map a POJO to below entity class using modelmapper and trying to save these entities into the database.All the fields are getting mapped and saved as expected except the foreign key value which is coming as null. Also, the userid is auto generated.Can you please help me how can I save the user id in vehicle table using modelmapper??
My User Entity class
#Entity
#Table(name = "usr")
class User{
#Id
#Column(name = "user_id", updatable = false, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
private String username;
#OneToMany(mappedBy = "user",cascade = CascadeType.ALL)
private List<Vehicle> vehicles= new ArrayList<>();
//getters and setters
}
My Vehicles Entity Class:
#Entity
#Table(name = "vehicle")
class Vehicle{
#Id
#Column(name = "vehicle_id", updatable = false, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long vehicleId;
private String vehicleName;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_fk" , nullable = false)
private User user;
//getters and setters
}
My ModelMapping class:
#Service
public class UserService {
#Autowired
private UserDetailsService userDetailsService;
public void saveUserDetails(UserDetails userDetails
User targetuser{
UserDetails sourcePojo= userDetails
User targetEntity= targetuser
ModelMapper modelMapper = new ModelMapper();
modelMapper.map(sourcePojo, targetEntity);
userDetailsService.save(targetEntity);
}
}
You Can try with making annotation more specific this :
#OneToMany(mappedBy = "user",
targetEntity = Vehicle.class,
cascade = CascadeType.ALL)
private List<Vehicle> vehicles= new ArrayList<>();
And
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_fk" ,
referencedColumnName = "user_id",
nullable = false)
private User user;
And I think you have to remove annotation for auto generation of userid
As per my understanding issue is due to Auto generation of userid is done while saving an entry to DB. But when we mapped userid to vehicle it is null as it is not generated.
This question already has answers here:
Infinite Recursion with Jackson JSON and Hibernate JPA issue
(29 answers)
Closed 3 years ago.
I really don't know how does the security and spring data jpa work, but when I try to receive other users data from database it's acting like an infinite loop and shows only my account info over 9k times and then after few seconds it crashes in web browser with error SyntaxError: JSON.parse: unterminated string literal at line 1 column 39978 of the JSON data,
My userRepository is a part of my UserDetailsServiceImplementation which is used in spring security as authentication with SQL database. It's work fine, I can log in on my account, but I can't query and view others' data info.
I've got no idea how to bypass it. Maybe it's a security feature to don't get access to other people credentials.
UserRepository
#Repository
public interface UserRepository extends JpaRepository<User, Long>{
public User findByUsername(String username);
#Query("SELECT * FROM user")
public List<User> findAll();
}
Controller
#RestController
#RequestMapping("/v1/api")
public class HomeApiController {
#Autowired
private UserRepository userRepository;
#GetMapping("/users")
public List<User> getUsers() {
return userRepository.findAll();
}
}
User
#Entity
#Table
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String username;
#Column
#JsonIgnore
private String password;
#Column
private boolean enabled;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Authority> authorities;
public User() {
}
then field based constructor + getters and setters
Authority
#Entity
#Table
public class Authority {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column
private String role;
#ManyToMany(mappedBy = "authorities")
private Set<User> user;
public Authority() {
}
field constructor + getters and setters
i expected to query and retrieve all other users in user table in database which is also used to authorize users based on roles in system.
json output shows...
{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":[{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":[{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":[{"id":1,"username":"Admin","enabled":true,"authorities":[{"role":"ROLE_USER","user":
and it's infinite nested.
i think there's something wrong with authorities
when i clear user_role table then output works great
id 1
username "Admin"
enabled true
authorities []
what's wrong?
you have to annotate the User set in the Authority class with #JsonIgnore or Annotate the Authorities set in the User class depending on what you need in your API call.
#Entity
#Table
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String username;
#Column
#JsonIgnore
private String password;
#Column
private boolean enabled;
#JsonIgnore
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Authority> authorities;
public User() {
}
Or
#Entity
#Table
public class Authority {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column
private String role;
#JsonIgnore
#ManyToMany(mappedBy = "authorities")
private Set<User> user;
public Authority() {
}
EDIT: Also I do recommend using DTOs to minimize the coupling and avoid such problems