I'm writing a web application (that represents online banking work). I have an entity "user" and a corresponding table in the database. Also, I have a registration form that transfers entered data via Thymeleaf.
My entity has two rows that have default values in the database. These are "role" row and "status". I set the default value in the database.
But, when I do input data in the registration form and click "sign up", the data transfers to the database successfully, however, two rows (role and status) that have their own default values are of a null type. Why the default values aren't being set automatically?
My entity class:
@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
@Enumerated(value = EnumType.STRING)
@Column(name = "status")
private Status status;
@Enumerated(value = EnumType.STRING)
@Column(name = "role")
private Role role;
}
My settings in the database table:
When I check the property "NOT NULL", I'm receiving an error that tells me that the row "role" cannot be null.
That's how my table looks like when I register new users:
My controller:
@Controller
@RequestMapping("/auth")
public class AuthController {
private final UserRepository userRepository;
@Autowired
public AuthController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping("/login")
public String login() {
return "/auth/login";
}
@GetMapping("/signup")
public String signUp(User user, Model model) {
return "/auth/registration";
}
@PostMapping("/signup")
public String signUpProcess(@ModelAttribute User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "redirect:/auth/registration";
}
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(12);
user.setPassword(passwordEncoder.encode(user.getPassword()));
userRepository.save(user);
return "redirect:/auth/login";
}
}
Registration page:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://thymeleaf.org">
<head>
<!-- Required meta tags -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Registration</title>
<!-- This style must be at the top -->
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="/static/login.css">
</head>
<body>
<form th:method="post" th:object="${user}"> <!-- added th:method and th:object -->
<div >
<img src="/static/images/login/codelib_logo.png" alt="" width="72" height="72">
<h1 >Registration</h1>
<p> Enter all the required information into the forms below. </p>
</div>
<div >
<input type="text" id="inputFirstName" th:field="*{firstName}" placeholder="First Name" required>
<label for="inputFirstName">First Name</label>
</div>
<div >
<input type="text" id="inputLastName" th:field="*{lastName}" placeholder="Last Name" required>
<label for="inputLastName">Last Name</label>
</div>
<div >
<input type="email" id="inputEmail" th:field="*{email}" placeholder="Email address" required autofocus>
<label for="inputEmail">Email address</label>
</div>
<div >
<input type="password" id="inputPassword" th:field="*{password}" placeholder="Password" required>
<label for="inputPassword">Password</label>
</div>
<button type="submit">Sign up</button>
<br>
<p>Already registered? <a href="/auth/login">Click to sign in</a></p>
<p >© BlackBank 2022</p>
</form>
<!-- Scripts related to Bootstrap -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X 965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH 8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM B07jRM" crossorigin="anonymous"></script>
</body>
</html>
If I haven't specified some valuable information, please, let me know.
CodePudding user response:
@cloumn annotation should be something like below
@Column(name = "status", nullable=false, length = 20, columnDefinition = "varchar(20) default 'ACTIVE'")
@Column(name = "role", nullable=false, length = 20, columnDefinition = "varchar(20) default 'USER'")
CodePudding user response:
DEFAULT
constraint defined on table will work in case of native query(in hibernate).
"INSERT INTO USERS (id, first_name, last_name, email, password) VALUES (v1, v2, v3, v5)"
-- // in this case the fields(status, role) are not specified and
the db will set default value(ACTIVE, USER)
another solution would be use annotation
@PrePersist
in your entity class to check the value of the fields and change it if is null(before object is saved).@PrePersist public void control() { if (status == null) setStatus("ACTIVE"); }
CodePudding user response:
Since the entity getting persisted has null values for those 2 fields it will override the specified defaults. You can apply 3 approaches
Assign default value in Entity class directly (can be overriden by entity setter)
private Role role = Roles.user;
Use Life cycle call back annotation @Prepersist/@PreUpdate (Most recommended, will override any existing value, can be used to perform logic also.)
As suggested by Amir use attribute "columnDefinition" (can be overriden by entity setter)