S
S
sur-pavel2021-01-28 20:55:45
Java
sur-pavel, 2021-01-28 20:55:45

How to create an object in hibernate without an optional field?

An entity is created in the application:

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(max = 50)
    @Column
    private String firstName;

    @NotNull
    @Size(max = 50)
    @Column
    private String lastName;

    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "project_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private Project project;

    public User() {
        super();
    }

    public User(@NotNull @Size(max = 50) String firstName, @NotNull @Size(max = 50) String lastName, Project project) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.project = project;
    }
//Getters, Setters, etc.

repository
public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findByProjectId(Long userId, Pageable pageable);
}

The UserController has two methods for creating an object:
@GetMapping("/users/add")
    public String showAddUser(Model model) {
        User user = new User();
        model.addAttribute("add", true);
        model.addAttribute("user", user);
        return "users/user-edit";
    }

    @PostMapping("/users/add")
    public String addUser(Model model, @ModelAttribute("user") User user) {        
        try {
            User newUser = userService.save(user);
            return "redirect:/users/" + String.valueOf(newUser.getId());
        } catch (Exception ex) {
            String errorMessage = ex.getMessage();
            logger.error(errorMessage);
            model.addAttribute("errorMessage", errorMessage);
            model.addAttribute("add", true);
            return "users/user-edit";
        }        
    }

on the object creation page (I use thymeleaf):
<form th:action="${add} ? @{/users/add} : @{/users/{userId}/edit(userId=${user.id})}"
              th:object="${user}" method="POST">
            <table border="0">
                <tr th:if="${user.id}">
                    <td>ID</td>
                    <td>:</td>
                    <td th:utext="${user.id}">...</td>             
                </tr>
                <tr>
                    <td>First Name</td>
                    <td>:</td>
                    <td><input type="text" th:field="*{firstName}" /></td>              
                </tr>
                <tr>
                    <td>Last Name</td>
                    <td>:</td>
                    <td><input type="text" th:field="*{lastName}" /></td>              
                </tr>                                
            </table>
            <input type="submit" th:value="${add} ? 'Create' : 'Update'" />
        </form>

When trying to create a User object (on the html creation page) without specifying a reference to the project object, it jumps out
nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : ru.surpavel.bugtrackingsystem.entity.User.project

If in the User class the project field is made nullable = true, then it pops up:
could not execute statement; SQL [n/a]; constraint[null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

How to fix it?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
O
Orkhan, 2021-01-28
Hasanly @azerphoenix

Good afternoon!
It will probably be better if you create a DTO from the client, and then convert it to Entity. This is not related to the question, so a little advice.
And it turns out that you form User on the client. And it is possible that project, since it is not created, is passed null.
And at the same time you have nullabe = false

@ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "project_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private Project project;

It turns out that you cannot create a user, but at the same time assign him a null project. That's why you have ConstraintViolationException
In general,
1) use DTO
2) Probably worth setting nullable = true

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question