Не удалось зафиксировать транзакцию JPA;Вложенное исключение - javax.persistence.RollbackException: ошибка при фиксации транзакции. - PullRequest
0 голосов
/ 22 сентября 2018

У меня ошибка при попытке вставить пользователя в базу данных.

Я сделал пользовательскую аннотацию, которая проверяет, совпадает ли пароль с паролем подтверждения, он работает, когда поле не совпадает, но когдасовпадения passowrd У меня есть эта ошибка:

enter image description here

Это мой код Это мое поле соответствует @Annotation:

package mereuta.marian.tennis01.annotations;


import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Constraint(validatedBy = FieldsValueMatchValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsValueMatch {

    String message() default "Fields values don't match!";

    String field();

    String fieldMatch();

    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    @Target({ ElementType.TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @interface List {
        FieldsValueMatch[] value();
    }
}

Этоэто полевой валидатор:

package mereuta.marian.tennis01.annotations;

import mereuta.marian.tennis01.model.Utilisateur;
import org.springframework.beans.BeanWrapperImpl;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class FieldsValueMatchValidator implements ConstraintValidator<FieldsValueMatch , Object> {

    private String field;
    private String fieldMatch;


    @Override
    public void initialize(FieldsValueMatch fieldsValueMatch) {
        this.field=fieldsValueMatch.field();
        this.fieldMatch=fieldsValueMatch.fieldMatch();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {


        Object fieldValue = new BeanWrapperImpl(value)
                .getPropertyValue(field);
        Object fieldMatchValue = new BeanWrapperImpl(value)
                .getPropertyValue(fieldMatch);

        if (fieldValue != null) {
            return fieldValue.equals(fieldMatchValue);
        } else {
            return fieldMatchValue == null;
        }
    }
}

Это моя сущность:

@FieldsValueMatch(field = "password", fieldMatch = "confirmPassword", 
message = "Password do not match!")
@Entity(name = "utilisateurs")
public class Utilisateur {
    @Id @GeneratedValue
    @Column(name = "id_utilisateur")
    private Integer id;
    @NotNull
    @Size(min = 4, max = 255)
    @Column(name = "password")
    private String password;
    @Transient
    @NotNull
    private String confirmPassword;

Это контроллер:

@PostMapping("/addUtilisateur")
    public String addUtilisateur(@Valid @ModelAttribute("utilisateur") Utilisateur utilisateur, BindingResult bindingResult, Model model) {


        if (bindingResult.hasErrors() ) {
            model.addAttribute("message", "le mot de passe ne correspond pas");
            return "utilisateur/formRegister";
        }


        utilisateurMetier.creerUtilisateur(utilisateur);

        return "utilisateur/utilisateurAjoute";


    }

И, наконец, представление:

<div class="container">
        <form id="contact" th:action="@{addUtilisateur}" method="post" th:object="${utilisateur}">
            <h3>Créer compte</h3>


                <input placeholder="password" type="password" th:field="*{password}" tabindex="2" required/>
                <span class="text text-danger" th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>

            </fieldset>


            <fieldset>

                <input placeholder="password" type="password" th:field="*{confirmPassword}" tabindex="2" required/>
                <span class="text text-danger" th:if="${#fields.hasErrors('confirmPassword')}"
                      th:errors="*{confirmPassword}" th:text="${message}"></span>


            </fieldset>

Для пользовательских аннотаций я нахожу пример: https://www.baeldung.com/spring-mvc-custom-validator

@Override
    public void creerUtilisateur(Utilisateur utilisateur) {

        Role role;
        float credit = 0;
        boolean actif = true;

        role = roleRepository.getOne(3);


        System.out.println(role);

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();


        utilisateur.setPassword(encoder.encode(utilisateur.getPassword()));

        utilisateur.setRole(role);
        utilisateur.setCredit(credit);
        utilisateur.setActif(actif);


        utilisateurRepository.save(utilisateur);
    }

Заранее благодарю за помощь

1 Ответ

0 голосов
/ 24 сентября 2018

Как уже упоминалось, исключение ContraintViolationException создается внутри метода 'creerUtilisateur'.Таким образом, проверка вашего bean-компонента Utilisateur во время его передачи в метод контроллера Spring MVC (addUtilisateur(@Valid @ModelAttribute("utilisateur")...) работает правильно, когда оба поля (пароль, verifyPassword) имеют одинаковое значение.Позже вы закодируете пароль и измените значение переменной экземпляра пароля Utilitsateur:

utilisateur.setPassword(encoder.encode(utilisateur.getPassword()));

Теперь «password» и «passwordConfirm» больше не равны!При сохранении этой сущности в utilisateurRepository.save(utilisateur); JPA снова проверяет вашу сущность с помощью bean-компонентов перед ее сохранением в базе данных (pre-persist).Проверка выполняется автоматически, когда JPA / Hibernate вызывает событие pre-persist, pre-update или pre-remove жизненного цикла.А затем выдается ContraintViolationException!

В вашем методе creerUtilisateur просто установите закодированный пароль для обоих, 'password' и 'passwordConfirm', переменных экземпляра, и тем самым убедитесь, что они по-прежнему проходят проверку на равенство в FieldsValueMatchValidator.isValid(Object value, ConstraintValidatorContext context):

 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
 final String encodedPassword = encoder.encode(utilisateur.getPassword());
 utilisateur.setPassword(encodedPassword);
 utilisateur.setPasswordConfirm(encodedPassword);
 //...
 utilisateurRepository.save(utilisateur);

Вы также можете попробовать настроить поведение проверки bean-компонента JPA:

https://www.thoughts -on-java.org / автоматическая проверка-entity-with-hibernate-validator /

Отключить проверку гибернации для слияния / обновления

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...