Spring MVC를 사용하여 웹 사이트를 만들고 지속성을 유지하기 위해 JPA 공급자로 Spring Data JPA와 Hibernate 4를 사용하고 있습니다. 검증은 현재 Hibernate Validator와 함께 처리되고있다. 저는 유효성 검사기가 두 번 호출되는 문제가있어서 그 이유를 알 수 없습니다. 주된 이유는 이것이 문제이기 때문에 두 번째 시간, 종속성이 유효성 검사기에 자동 추가되지 않고 널 포인터 예외가 발생하기 때문입니다. 다음은 실패에 이르기까지의 호출 순서는 다음과 같습니다JSR303 사용자 정의 유효성 검사기를 두 번 호출 중
- 등록 양식을 제출 먼저 NotDefaultSectValidator가 호출되고 사용자 개체의 'whereDidYouHearAboutUs'필드에 성공적으로 완료됩니다.
- UniqueUsernameValidator가 다음에 호출되고 '사용자 이름'필드 유효성 검사를 위해 성공적으로 완료됩니다.
- 컨트롤러의 'addUserFromForm'메서드가 시작되어 bindingResults 개체에서 오류가 발견되지 않습니다.
- 그러면 'addUser'메소드가 UserService 클래스에서 호출됩니다. 이 메소드는 'userRepository.save (user);'행에 도달합니다. 그러나 그 후에 'print.ln'라인을 실행하지 않습니다. 이 줄을 밟으면 'NotDefaultSectValidator'중단 점으로 돌아갑니다. 이 작업은 두 번째 완료되며 두 번째 유효성 검사기 'UniqueUsernameValidator'를 다시 입력합니다. 몇 가지 이유로 Spring이 DAO에서 Autowire에 실패하기 때문에 null 포인터 예외가 발생합니다.
왜 유효성 검사기가 두 번 호출되는지, 특히 'userRepository.save (user);'행을 건너 뛰는 이유에 대해 알려줄 수 있습니까? 이 유효성 검사기로 돌아 간다 고요?
많은 감사
다음내 user.java 클래스입니다
내 등록 컨트롤러 관련 방법 :
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String addUserFromForm(@Valid User user,
BindingResult bindingResult, RedirectAttributes ra) {
if (bindingResult.hasErrors()) {
return "user/register";
}
userService.addUser(user);
// Redirecting to avoid duplicate submission of the form
return "redirect:/user/" + user.getUsername();
}
내 서비스 클래스 :
package com.dating.service.impl;
import javax.transaction.Transactional;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.dating.domain.Role;
import com.dating.domain.User;
import com.dating.repository.RoleRepository;
import com.dating.repository.UserRepository;
import com.dating.repository.specification.UserSpecifications;
import com.dating.service.UserService;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Transactional
@Override
public void addUser(User user) {
user.setJoinDate(new LocalDate());
user.setEnabled(true);
Role role = roleRepository.findByName(Role.MEMBER);
if (role == null) {
role = new Role();
role.setName(Role.MEMBER);
}
user.addRole(role);
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
user.setPassword(encoder.encode(user.getPassword()));
userRepository.save(user);
System.out.println("User Saved");
}
@Override
public User getUserByUsername(String username) {
return userRepository.findByUsername(username);
}
@Override
public Iterable<User> getAllUsers() {
return userRepository.findAll();
}
@Override
public void updateDetails(User user) {
userRepository.save(user);
}
@Override
public Iterable<User> lastNameIsLike(String searchTerm) {
return userRepository.findAll(UserSpecifications
.lastNameIsLike(searchTerm));
}
}
내 번호 tDefaultSelect 검사기 :
package com.dating.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import com.dating.annotation.NotDefaultSelect;
public class NotDefaultSelectValidator implements
ConstraintValidator<NotDefaultSelect, String> {
@Override
public void initialize(NotDefaultSelect constraint) {
}
@Override
public boolean isValid(String selectedValue, ConstraintValidatorContext ctx) {
if (selectedValue == null) {
return false;
}
if (selectedValue.equals("") || selectedValue.equals("0")
|| selectedValue.equalsIgnoreCase("default")
|| selectedValue.equalsIgnoreCase("please select")) {
return false;
}
return true;
}
}
내 uniqueUsername 검사기 :
package com.dating.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import com.dating.annotation.UniqueUsername;
import com.dating.repository.UserRepository;
public class UniqueUsernameValidator implements
ConstraintValidator<UniqueUsername, String> {
@Autowired
private UserRepository userRepository;
@Override
public void initialize(UniqueUsername constraint) {
}
@Override
public boolean isValid(String username, ConstraintValidatorContext ctx) {
if (username == null || userRepository.findByUsername(username) == null) {
return true;
}
return false;
}
}
내 UserRepository :
package com.dating.repository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import com.dating.domain.User;
//Spring Data JPA Marker interfaces being extended for automatic CRUD repository creation
public interface UserRepository extends CrudRepository<User, Long>, JpaSpecificationExecutor<User> {
//Automatic query creation from method name
public User findByUsername(String username);
}
마지막으로 내 지속성-의 context.xml 파일
<!-- Data source properties -->
<util:properties id="dataSourceSettings" location="classpath:datasource.properties" />
<!-- Pooled data source using BoneCP -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<property name="driverClass" value="#{dataSourceSettings['jdbc.driverClass']}" />
<property name="jdbcUrl" value="#{dataSourceSettings['jdbc.url']}" />
<property name="username" value="#{dataSourceSettings['jdbc.username']}" />
<property name="password" value="#{dataSourceSettings['jdbc.password']}" />
<property name="idleConnectionTestPeriodInMinutes" value="60" />
<property name="idleMaxAgeInMinutes" value="240" />
<property name="maxConnectionsPerPartition" value="30" />
<property name="minConnectionsPerPartition" value="10" />
<property name="partitionCount" value="3" />
<property name="acquireIncrement" value="5" />
<property name="statementsCacheSize" value="100" />
<property name="releaseHelperThreads" value="3" />
</bean>
<!-- JPA entity manager factory bean -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.dating.domain" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">#{dataSourceSettings['hibernate.dialect']}</prop>
<prop key="hibernate.hbm2ddl.auto">#{dataSourceSettings['hibernate.hbm2ddl.auto']}
</prop>
<prop key="hibernate.show_sql">#{dataSourceSettings['hibernate.show_sql']}</prop>
<prop key="hibernate.format_sql">#{dataSourceSettings['hibernate.format_sql']}</prop>
<prop key="hibernate.use_sql_comments">#{dataSourceSettings['hibernate.use_sql_comments']}
</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<context:annotation-config />
<jpa:repositories base-package="com.dating.repository"/>
여기에서 코드를 좁히십시오. –
먼저 인스턴스가 Spring에 의해 유효성이 확인되면 저장하기 전에 최대 절전 모드로 유효성이 검사됩니다. 의존성이 정확하게 주입 (또는 잡아 당겨 지도록)하거나 hibernate/jpa에 대한 검증을 사용하지 않도록 validator를 수정하십시오. –
개인 필드를 autowiring하면 리플렉션을 통해서만 주입 할 수 있습니다. 또한 setter 또는 생성자 인수를 제공하여 주입해야합니다. 모든 주사가 여러분이 알고있는 봄에 의해 이루어져야하는 것은 아닙니다. – Bart