#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false, unique = true)
private Long id;
private String firstName;
private String lastName;
private String email;
private String password;
#OneToOne(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy = "user")
private UserProfile userProfile;
// Hibernate requires a no-arg constructor
public User() {
}
public User(String firstName, String lastName, String email, String password) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.password = password;
}
// Getters and Setters (Omitted for brevity)
}
UserProfile
#Entity
#Table(name = "user_profiles")
public class UserProfile implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String phoneNumber;
private String gender;
private String address1;
private String address2;
private String street;
private String city;
private String state;
private String country;
private String zipCode;
#OneToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "user_id", nullable = false)
private User user;
public UserProfile() {
}
public UserProfile(String phoneNumber, String gender,
String address1, String address2, String street, String city,
String state, String country, String zipCode) {
this.phoneNumber = phoneNumber;
this.gender = gender;
this.address1 = address1;
this.address2 = address2;
this.street = street;
this.city = city;
this.state = state;
this.country = country;
this.zipCode = zipCode;
}
// Getters and Setters (Omitted for brevity)
}
My Service
#Component
public class UserService {
#Autowired
UserRepo userRepo;
public ResponseEntity<User> createUser(String firstName, String lastName, String email, String password){
User user=new User(firstName,lastName,email,password);
return new ResponseEntity<>(user,HttpStatus.OK);
}
public ResponseEntity<List<User>> savedataBase(User user){
userRepo.save(user);
return new ResponseEntity<>( userRepo.findAll(), HttpStatus.OK);
}
}
#Component
public class UserPServer {
#Autowired
UserProfileRepo userProfileRepo;
public ResponseEntity<List<UserProfile>> save(UserProfile userProfile){
userProfileRepo.save(userProfile);
return new ResponseEntity<>( userProfileRepo.findAll(), HttpStatus.OK);
}
}
My Controller
#RestController
#RequestMapping("/user")
public class UserController {
#Autowired
UserService userService;
#GetMapping("/create/{firsName}/{lastName}/{email}/{password}")
public ResponseEntity<User> create(#PathVariable("firsName") String firstName,
#PathVariable("lastName") String lastName,
#PathVariable("email") String email,
#PathVariable("password") String password){
return userService.createUser(firstName,lastName,email,password);
}
#PostMapping("/usersave")
public ResponseEntity<List<User>> saveDateBase(#RequestBody User users){
return userService.savedataBase(users);
}
}
#RestController
#RequestMapping("/userprofile")
public class UserPConroller {
#Autowired
UserPServer userPServer;
#PostMapping("/userpsave")
public ResponseEntity<List<UserProfile>> savep(UserProfile userProfile){
return userPServer.save(userProfile);
}
}
UserProfile classes like above
I get error like this:
*Column 'user_id' cannot be null
2019-12-26 11:27:35.618 ERROR 6540 --- [nio-8883-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
edit your application.properties file like this
spring.jpa.hibernate.ddl-auto = update
Once you decided who is the "parent" in this relationship you should save the child first with its repository.
Lets assume it is the User.
You would do something like this in your controller
UserProfile newUser = user.getUserProfile();
userProfileRepository.save(newUser);
userRepository.save(user);
This guarantee garantee that the relation is successful.
Related
I am trying to set up a testing environment using an expectedPojo, but I continue getting the error that the constructor is undefined. From the error, I see it is listing the LocalTimeDate in the expectedPojo as String which may be the cause, but I am unfamiliar with testing with a LocalDateTime entry.
public class UserPojo {
private int id;
private String name;
private String email;
private String phoneNumber;
private String username;
private String password;
private boolean darkModePreference;
private LocalDateTime registerDate;
private int roleId;
public UserPojo() {
}
public UserPojo(int id, String name, String email, String phoneNumber, String username, String password,
boolean darkModePreference, LocalDateTime registerDate, int roleId) {
super();
this.id = id;
this.name = name;
this.email = email;
this.phoneNumber = phoneNumber;
this.username = username;
this.password = password;
this.darkModePreference = darkModePreference;
this.registerDate = registerDate;
this.roleId = roleId;
}
#ExtendWith(MockitoExtension.class)
public class LoginAndRegisterTest {
#Mock
UserDao userDao;
#InjectMocks
UserServiceImpl userService;
private UserPojo expectedPojo;
private UserEntity dummyEntity;
#BeforeEach
public void setup() {
LocalDateTime now;
expectedPojo = new UserPojo(1, "Goldendeep", "golden#coolkids.com", "333-343-3434", "golden", "kaur11", false, "2022-06-25T22:37:24.894", 2);
dummyEntity = new UserEntity(1, "Goldendeep", "golden#coolkids.com", "333-343-3434", "golden", "kaur11", false, "2022-06-25T22:37:24.894", 2);
}
While creating the object of UserPojo class you are passing the second-to-last argument as String instead an argument of LocalDateTime type is expected, which is causing the issue. Either provide the argument of LocalDateTime type or modify the constructor definition to accept String argument.
I have a common User class and its descendants with a specific role. How do I create an object in the registration controller, depending on the choice in the registration form? Can this be done via radio button and thymeleaf?
#Getter
#Setter
#ToString
#EqualsAndHashCode
#NoArgsConstructor
#AllArgsConstructor
#MappedSuperclass
public class User implements UserDetails, Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
#Transient
private String matchingPassword;
private String name;
private String surname;
private String patronymic;
private LocalDate birthday;
private String hometown;
private String number;
private String mail;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(
name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private List<Role> roles;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
#Data
#EqualsAndHashCode(callSuper = true)
#ToString(callSuper = true)
#NoArgsConstructor
#Entity(name = "Student")
#Table(name = "student", schema = "public")
public class Student extends User {
private String studentIdNumber;
private String groupNumber;
private String academicPerformance;
private String faculty;
private String department;
private long rating;
#Builder
public Student(Long id,
String username,
String password,
String matchingPassword,
String name,
String surname,
String patronymic,
LocalDate birthday,
String hometown,
String number,
String mail,
String studentIdNumber,
String groupNumber,
String academicPerformance,
String faculty,
String department,
List<Role> roles) {
super(id, username, password, matchingPassword, name, patronymic, surname, birthday, hometown, number, mail, roles);
this.studentIdNumber = studentIdNumber;
this.groupNumber = groupNumber;
this.academicPerformance = academicPerformance;
this.faculty = faculty;
this.department = department;
this.rating = 0;
}
}
#Data
#EqualsAndHashCode(callSuper = true)
#ToString(callSuper = true)
#NoArgsConstructor
#Entity(name = "Director")
#Table(name = "director", schema = "public")
public class Director extends User {
private String department;
#Builder
public Director(Long id,
String username,
String password,
String matchingPassword,
String name,
String surname,
String patronymic,
LocalDate birthday,
String hometown,
String number,
String mail,
String department,
List<Role> roles) {
super(id,
username,
password,
matchingPassword,
name,
surname,
patronymic,
birthday,
hometown,
number,
mail,
roles);
this.department = department;
}
}
The controller in which the object is created for writing to the database and defining the role:
#GetMapping("/registration")
public String showRegistrationForm(Model model) {
log.info("showRegistrationForm method called");
model.addAttribute("newUser", new User()); <----- Creation of a specific object. How!?
model.addAttribute("avatar", "default_avatar.png");
model.addAttribute("username", "Unknown");
return "registration";
}
I just added mapping where the user selects a role.
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***");
}
}
}
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.
I have the next situation. I ahve entity object User:
package models;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import org.hibernate.annotations.Proxy;
#Entity
#Table(name="users")
#Proxy(lazy=true)
public class User {
private int id;
private String login;
private String password;
private String name;
private String email;
private Integer age;
private String country;
private Set<UserRole> roles = new HashSet<UserRole>();
private UserStatus status;
private Date created;
private Date updated;
public User() {
status=UserStatus.A;
}
public User(String user_login, String user_password, String user_name, String user_email) {
this.login = user_login;
this.password = user_password;
this.name = user_name;
this.email = user_email;
status=UserStatus.A;
}
public User(String user_login, String user_password, String user_name, String user_email, int age) {
this(user_login, user_password, user_name, user_email);
this.age = age;
}
public User(String user_login, String user_password, String user_name, String user_email, int age, String country) {
this(user_login, user_password, user_name, user_email, age);
this.country = country;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="user_id", unique = true)
public int getId() {
return id;
}
public void setId(int user_id) {
this.id = user_id;
}
#Column(name="user_login")
public String getLogin() {
return login;
}
public void setLogin(String user_login) {
this.login = user_login;
}
#Column(name="user_password")
public String getPassword() {
return password;
}
public void setPassword(String user_password) {
this.password = user_password;
}
#Column(name="user_name")
public String getName() {
return name;
}
public void setName(String user_name) {
this.name = user_name;
}
#Column(name="user_email")
public String getEmail() {
return email;
}
public void setEmail(String user_email) {
this.email = user_email;
}
#Column(name="user_age")
public Integer getAge() {
return age;
}
public void setAge(Integer user_age) {
this.age = user_age;
}
#Column(name="user_country")
public String getCountry() {
return country;
}
public void setCountry(String user_country) {
this.country = user_country;
}
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "users_to_userroles", joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "user_role_id ") })
public Set<UserRole> getRoles() {
return roles;
}
public void setRoles(Set<UserRole> user_roles) {
this.roles = user_roles;
}
#Column(name="user_status")
#Enumerated(EnumType.STRING)
public UserStatus getStatus() {
return status;
}
public void setStatus(UserStatus status) {
this.status = status;
}
#Transient
#Column(name="user_created")
public Date getCreated() {
return created;
}
public void setCreated(Date user_created) {
this.created = user_created;
}
#Transient
#Column(name="user_updated")
public Date getUpdated() {
return updated;
}
public void setUpdated(Date user_updated) {
this.updated = user_updated;
}
}
And JSP page (simple form, not related to question) with the form to create new user and table to show all existing users. I have used binding between form and Entity object User (it is inside controller):
User user = new User();
List<User> users = userService.getAllUsers();//to fill table with users
List<UserRole> userRoles = userRolesService.getAllRoles();//to fill tables with users
model.addAttribute("rolesList", userRoles);
model.addAttribute("users", users);
model.put("adminForm", user);//Here adminForm is the name of form in JSP page
Now what is the problem: as you see User has two fields user_created and user_updated (they are created automatically by Postgres server). They are forwarded withh all other fields to table in JSP page. BUT my form in JSP does not provide these fields (no need - right)))), so they are null when transfered from form to controller. And now Hibernate can not add line on Postgres server because two fields are empty((( So my question is:
can I somehow mark these columns as #Transient but only when I save entity not read it from database.
I know I still can bind separate field in form not the whole object. But still is it possible to do what I ask? With existing configuration, new User is saved but these two fields are not read and JSP table columns are empty(((
You need to set the insertable and updatable properties of your column mapping to false. This will make the field read-only for Hibernate.
#Column(name="user_created", insertable=false, updatable=false)