spring boot mysql jpa Command Line Runner problem - java

I want to create a user within the run () method using CommandLineRunner. I want to automatically call this method and register it with JPA as soon as Tomcat runs. Below I share the codes I use within the project.When I ran it this way, the tomcat server worked fine, the system started but was not registered to the database. How do I fix this?
User
#Data
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private int id;
#Column(name = "email")
#Email(message = "*Please provide a valid Email")
#NotEmpty(message = "*Please provide an email")
private String email;
#Column(name = "password")
#Length(min = 5, message = "*Your password must have at least 5 characters")
#NotEmpty(message = "*Please provide your password")
private String password;
#Column(name = "name")
#NotEmpty(message = "*Please provide your name")
private String name;
#Column(name = "last_name")
#NotEmpty(message = "*Please provide your last name")
private String lastName;
#Column(name = "active")
private int active;
//JOIN tables
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
public User() {};
public User(String email, String password, String name, String lastName, int active) {
this.email=email;
this.password=password;
this.name=name;
this.lastName=lastName;
this.active=active;
}
//G&S
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
Role
#Data
#Entity
#Table(name = "role")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "role_id")
private int id;
#Column(name = "role")
private String role;
//G&S
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
UserRepository
#Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
RoleRepository
#Repository("roleRepository")
public interface RoleRepository extends JpaRepository<Role, Integer> {
Role findByRole(String role);
}
Service
public class ServiceImplement implements CommandLineRunner{
#Autowired
UserService userService;
#Autowired
UserRepository userRepository;
#Autowired
RoleRepository roleRepository;
//$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62 = umut1234
User umut = null;
Role userRole = null;
#Override
public void run(String... args) throws Exception {
umut = new User();
umut.setEmail("umut#umut.com");
umut.setPassword("$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62");
umut.setName("Umut");
umut.setLastName("Eren");
umut.setActive(1);
userRole = roleRepository.findByRole("ADMIN");
umut.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(umut);
System.out.println("***Generated***");
}
}

import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
// add these 2 lines and change your impelentation to ApplicationRunner
#Component
#Order(value = 1)
public class ServiceImplement implements ApplicationRunner{
#Autowired
UserService userService;
#Autowired
UserRepository userRepository;
#Autowired
RoleRepository roleRepository;
//$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62 = umut1234
User umut = null;
Role userRole = null;
#Override
public void run(ApplicationArguments args) throws Exception {
umut = new User();
umut.setEmail("umut#umut.com");
umut.setPassword("$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62");
umut.setName("Umut");
umut.setLastName("Eren");
umut.setActive(1);
//save user before add roles to it
userRepository.save(umut);
userRole = roleRepository.findByRole("ADMIN");
umut.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(umut);
System.out.println("***Generated***");
}
}

public class ServiceImplement implements ApplicationRunner {
#Autowired
UserService userService;
#Autowired
UserRepository userRepository;
#Autowired
RoleRepository roleRepository;
User umut = null;
Role userRole = null;
#Override
public void run(ApplicationArguments args) throws Exception {
String arguments = String.join(" | ", args.getSourceArgs());
System.out.println(arguments);
if(args.getNonOptionArgs().contains("-register"){
umut = new User();
umut.setEmail("umut#umut.com");
umut.setPassword("$2y$12$YN6IjSzj5DYvSpv6jofxV.p8C.zSKKTdnDZ4oc0XT0TmODcUe.s62");
umut.setName("Umut");
umut.setLastName("Eren");
umut.setActive(1);
userRole = roleRepository.findByRole("ADMIN");
umut.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(umut);
System.out.println("***Generated***");
}
}
}

Related

Don't know how to findByRole to return a customised list of users

I am trying to list users in my application based on role. I have an endpoint in my controller which tries to call my userService class .findByRoles method but I dont know how to put the role I want to without having the role as a string(wont work).
adminController.java method:
#GetMapping(path="/users")
public String showUsers( Model model){
var userList = (List<User>) userService.findByRoles("ROLE_TEACHER"); // dont know how to pass a role here
model.addAttribute("userList", userList);
return "users";
}
User.java:
#Entity
#Table(name = "user_table", schema = "public")
public class User {
#Id
#Column(name = "user_id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long user_id;
#Column(name = "name")
private String name;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "confirmed")
private boolean confirmed;
#ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DETACH}, fetch = FetchType.EAGER)
#JoinTable(
name = "user_role_table",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "role_id"))
private Collection<Role> roles = new HashSet<>();
/*******************************************
* Setters and getters
*******************************************/
public Long getId() {
return user_id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return password;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setConfirmed(Boolean confirmed) {
this.confirmed = confirmed;
}
public Boolean getConfirmed() {
return confirmed;
}
public void setRoles(Collection roles) {
this.roles = roles;
}
public Collection<Role> getRoles() { return this.roles;
}
}
userRepository:
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
User findByEmail(String email);
User findByRoles(Role role);
}
roleRepository:
public interface RoleRepository extends JpaRepository<Role, Long> {
Role findByName(String name);
}
IUserService.java:
public interface IUserService {
User registerNewUserAccount(UserDto userDto);
List<User> findAll();
Optional<User> findById(Long id);
User findByRoles(Role role);
public void delete(Long id);
public User updateConfirmed(Long id);
}
UserService.java method:
#Override
public User findByRoles(Role role) {
return userRepository.findByRoles(role);
}
Any tips how I can go about to fix this issue?
After tweaking around with the classes I think the most logical method to fix the issue is to use roleRepository method findByName. Furthermore, created findAllByRoles in userRepository, IUserService & UserService for returning a list(check my comment on this answer).
Changed IUserService.java to:
public interface IUserService {
User registerNewUserAccount(UserDto userDto);
List<User> findAll();
Optional<User> findById(Long id);
List<User> findAllByRoles(String roles); //Added this new method (VERY IMPORTANT for returning multiple users)
User findByRoles(String roles);
public void delete(Long id);
public User updateConfirmed(Long id);
}
Changed UserService.java method to:
#Override
public User findByRoles(String roles) {
return userRepository.findByRoles(roleRepository.findByName(roles)); // Using roleRepository here
}
// Added below findAllbyRoles to return a list
#Override
public List<User> findAllByRoles(String roles){
return userRepository.findAllByRoles(roleRepository.findByName(roles));
}
Changed adminController.java method to:
#GetMapping(path="/users")
public String showUsers( Model model){
List<User> userList = userService.findAllByRoles("ROLE_STUDENT");
userList.addAll(userService.findAllByRoles("ROLE_TEACHER"));
model.addAttribute("userList", userList);
return "users";
}

JPA Repository Findbyid Returns Repeated List

I am having a problem with my retriveUser method. When I run finbyid method it returns the same repeated values. You can see my repository, user, and userService classes and the result below.
[![findbyid method result][1]][1]
My User Repository Class
package io.javabrains.springsecurity.jpa;
import io.javabrains.*;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import io.javabrains.springsecurity.jpa.models.User;
#Repository
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUserName(String userName);
}
My User Class
#Entity
#Table(name="app_user")
public class User implements Serializable {
#Id
#GeneratedValue(strategy =GenerationType.IDENTITY)
private int id;
private String userName;
private String password;
private boolean active;
private String role;
private String city;
public User(String userName, boolean active, String role, String city) {
super();
this.userName = userName;
this.active = active;
this.role = role;
this.city = city;
}
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "user_cities", joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "city_id", referencedColumnName = "id"))
private Collection<UserCity> usercities = new ArrayList<UserCity>() ;
public Collection<UserCity> getUsercities() {
return usercities;
}
public void setUsercities(Collection<UserCity> usercities) {
this.usercities = usercities;
}
public User() {}
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;
}
}
My Service Class
#RestController
public class HomeResource {
#Autowired
private BCryptPasswordEncoder bcryptPasswordEncoder;
#Autowired
private WeatherService weatherService;
#Autowired
private CityRepository cityRepository;
#Autowired
private UserRepository userRepo;
#GetMapping("/")
public String home() {
return ("<h1>Welcome</h1>");
}
#GetMapping("/user")
public String user() {
return ("Welcome User");
}
#GetMapping("/admin")
public String admin() {
return ("<h1>Welcome Admin</h1>");
}
#GetMapping("/getCities")
public List<UserCity> getCities()
{
return cityRepository.findAll();
}
#GetMapping("/users/{id}")
public ResponseEntity<User> retriveUser(#PathVariable int id){
Optional<User> a=userRepo.findById(id);
return new ResponseEntity<User>(a.get(),HttpStatus.OK);
}
Thanks in advance for your help.
Sincerely
[1]: https://i.stack.imgur.com/gNhO7.png
The repeated value is a nested user from the usercities collection in a User object.
The user (id: 1) has a usercities collection containing one UserCity object (cityName: 'bursa' and users containing the same user (id: 1)). Thus, the user (id: 1) is recursively displayed.
You can add #JsonIgnore annotation to your property (usercities in User or users in UserCity) to cut the recursion.

TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing

I'm trying to store user details into the following tables: user, role, user_role. When trying to save the details, it throws the following error.
Error during managed flush
[org.hibernate.TransientPropertyValueException: object references an
unsaved transient instance - save the transient instance before
flushing
Here user_role is the parent table, user and role tables are the children. I tried with cascade = CASCADE.ALL. Even though it trows the same error.
User.java
#Entity
public class User implements UserDetails, Serializable{
private static final long serialVersionUID = 902783495L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="Id", nullable=false, updatable = false)
private Long id;
private String username;
private String password;
private String email;
private boolean enabled = true;
#OneToMany(mappedBy = "user", cascade=CascadeType.ALL, fetch = FetchType.EAGER)
#JsonIgnore
private Set<UserRole> userRoles = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long 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 void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = new HashSet<>();
userRoles.forEach(ur -> authorities.add(new Authority(ur.getRole().getName())));
return authorities;
}
#Override
public boolean isAccountNonExpired() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isAccountNonLocked() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
#Override
public boolean isEnabled() {
return enabled;
}
}
Role.java
#Entity
public class Role implements Serializable{
private static final long serialVersionUID = 890245234L;
#Id
private int roleId;
private String name;
#OneToMany(mappedBy = "role", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
private Set<UserRole> userRoles = new HashSet<>();
public Role(){}
public int getRoleId() {
return roleId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
}
UserRole.java
#Entity
#Table(name="user_role")
public class UserRole implements Serializable {
private static final long serialVersionUID = 890345L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long userRoleId;
public UserRole () {}
public UserRole (User user, Role role) {
this.user = user;
this.role = role;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
#ManyToOne(fetch = FetchType.EAGER)
private Role role;
public long getUserRoleId() {
return userRoleId;
}
public void setUserRoleId(long userRoleId) {
this.userRoleId = userRoleId;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
Here role_id is primary key and you are trying to set 1 as role_id every time, make new primary key with
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long seqNo;

Error: AnnotationException: mappedBy reference an unknown target entity property

I'm creating Spring Boot Application with JPA PostgreSQL.
When I compile my spring project, got the following error.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: eveserver.core.entity.User.name in eveserver.core.entity.Role.users
Please, help me to understand what i'm doing wrong.
This is my User.java
package eveserver.core.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;
#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "name")
private String username;
#JsonIgnore
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
private boolean enabled = false;
#ManyToMany
#JoinTable(name = "user_role",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "role_id", referencedColumnName = "id"))
private Set<Role> roles;
public User(){ }
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public User(String username, String password, String email, Set<Role> roles) {
this.username = username;
this.password = password;
this.email = email;
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long 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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
public void enable(){
enabled = true;
}
public void disable(){
enabled = false;
}
}
Role.java
package eveserver.core.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "role")
public class Role implements GrantedAuthority {
#Id
#GeneratedValue
private Long id;
private String name;
#ManyToMany(mappedBy = "role")
#JsonIgnore
private Set<User> users;
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;
}
#Override
public boolean equals(Object obj){
if (obj instanceof Role){
Role r = (Role)obj;
if (r.getId()==this.getId()){
return true;
}
}
return false;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
#Override
public String getAuthority() {
return getName();
}
}
and this is my tables
In your User class, you have a property called roles:
public Set<Role> getRoles() {
return roles;
}
In your Role class, this:
#ManyToMany(mappedBy = "role")
#JsonIgnore
private Set<User> users;
should be:
#ManyToMany(mappedBy = "roles")
#JsonIgnore
private Set<User> users;
mappedBy = "something" is saying, effectively, "within this other entity, there's a property called something that gets a list of entities of this type (the current type that you're in when you use the #ManyToMany annotation). It is not specifying a type or class name like Role.

Does Spring Save Relationship Data too in Rest Call?

So If I have a User and a UserRole Table like soo..
User Class
package app.repo.User;
import javax.persistence.*;
import java.util.Set;
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Version
private Long version;
#Column(nullable = false)
private String username;
#Column(nullable = false)
private String password;
#OneToMany(mappedBy = "user")
private Set<UserRole> roles;
protected User() {}
public User(String username, String password) {
this.username = username;
this.password = password;
}
#Override
public String toString() {
return String.format(
"User[id=%d, username='%s', password='%s']",
id, username, password);
}
public long getId() {
return id;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<UserRole> getRoles() {
return roles;
}
public void setRoles(Set<UserRole> roles) {
this.roles = roles;
}
}
UserRole Class
package app.repo.User;
import javax.persistence.*;
#Entity
#Table(name = "user_roles")
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Version
private Long version;
#Column(name = "role_name")
private String roleName;
#ManyToOne
private User user;
public UserRole() {
}
public UserRole(String roleName, User user) {
this.roleName = roleName;
this.user = user;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public void setUser(User user) {
this.user = user;
}
}
The above example has a oneToMany relationship with UserRole and a ManyToOne Relationship with user.
My first question is... is it possible to save User and UserRole in one save like so...
userDao.save(user);
And second question is. How would I set that up in a JSON post call ? and how would this be done. This is what I am doing now
{
"userId":"1",
"userName":"RestMan",
"password":"happy",
"version":"1",
"email":"restman#gmail.com",
"enabled":"1",
"roles": {
{"user":"1","role_name":"ROLE_COOLGUY"}
}
}
Otherwise I am thinking to just create a Model that saves the two separately in one method
Change the annotation like this : #OneToMany(cascade = CascadeType.ALL)

Categories

Resources