Home > Back-end >  MySQL doesn't set a default value while adding a new row to the table
MySQL doesn't set a default value while adding a new row to the table

Time:02-13

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:

enter image description here

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:

enter image description here

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 >&copy; 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:

  1. 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)

  1. 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)

  • Related