@sur-pavel

Как в hibernate создать объект без поля optional?

В приложении создана сущность:
@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.

репозиторий
public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findByProjectId(Long userId, Pageable pageable);
}

В UserController есть два метода для создания объекта:
@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";
        }        
    }

на странице создания объекта (использую 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>

При попытке создания объекта User (на html странице создания) без указания ссылки на объект project выпрыгивает
nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : ru.surpavel.bugtrackingsystem.entity.User.project

Если в классе User поле project сделать nullable = true, то выскакивает:
could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

Как это исправить?
  • Вопрос задан
  • 175 просмотров
Пригласить эксперта
Ответы на вопрос 1
azerphoenix
@azerphoenix Куратор тега Java
Java Software Engineer
Добрый день!
Наверное будет лучше, если вы с клиента будете создавать DTO, а его уже конвертровать в Entity. Это не связано с вопросом, так небольшой совет.
А то получается, что вы на клиенте формируете User. И возможно, что project, так как он не создается передается null.
А при этом у вас nullabe = false
@ManyToOne(fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "project_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @JsonIgnore
    private Project project;

Получается нельзя создать юзера, но при этом назначить ему null project. Потому у вас и ConstraintViolationException

В общем,
1) используйте DTO
2) Наверное, стоит поставить nullable = true
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы