java - Thymeleaf:将角色应用于用户时出现字段错误(一对多关系)
问题描述
我正在尝试制作一个 Thymeleaf 应用程序,该应用程序可以注册一个具有在注册期间选择的附加角色的帐户。这是一个可视化。我将尝试添加尽可能多的相关代码,以便更好地了解正在发生的事情,然后解释问题。
用户.java:
package com.example.demo.model;
<imports>
@Entity
@Table(name = "user", uniqueConstraints = @UniqueConstraint(columnNames = "account"))
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String account;
private String password;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="role_id", nullable=false)
private Role role;
@OneToMany(mappedBy = "user")
private Collection<Comment> comments;
public User() {
}
public User(String firstName, String lastName, String account, String password, Role role,
Collection<Comment> comments) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.account = account;
this.password = password;
this.role = role;
this.comments = comments;
}
<getters and setters>
}
角色.java:
package com.example.demo.model;
<imports>
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(fetch=FetchType.LAZY, mappedBy = "role")
private Set<User> users = new HashSet<User>(0);
public Role() {
}
public Role(String name, Set<User> users) {
super();
this.name = name;
this.users = users;
}
<getters and setters>
}
评论.java:
<not important>
用户存储库.java:
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.demo.model.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByAccount(String account);
}
RoleRepository.java:
package com.example.demo.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.demo.model.Role;
@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
}
用户服务.java:
package com.example.demo.service;
<imports>
@Service("userService")
public class UserService {
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
public UserService(UserRepository userRepository) {
super();
this.userRepository = userRepository;
}
public User findByAccount(String account) {
return userRepository.findByAccount(account);
}
public void saveUser(User user) {
userRepository.save(user);
}
}
角色服务.java:
package com.example.demo.service;
<imports>
@Service
public class RoleService {
private RoleRepository roleRepository;
public RoleService(RoleRepository roleRepository) {
super();
this.roleRepository = roleRepository;
}
}
用户注册控制器.java:
package com.example.demo.web;
<imports>
@Controller
@RequestMapping("/registration")
public class UserRegistrationController {
private UserService userService;
@ModelAttribute("user")
public User user() {
return new User();
}
@Autowired
RoleRepository roleRepository;
@GetMapping
public String showRegistrationForm(Model model) {
model.addAttribute("roles", roleRepository.findAll());
return "registration";
}
@PostMapping
public String registerUserAccount(User user) {
System.out.println();
userService.saveUser(user);
return "redirect:/registration?success";
}
}
SecurityConfiguration.java(以防万一):
package com.example.demo.config;
<imports>
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(
"/registration**",
"/js/**",
"/css/**",
"/img/**").permitAll().anyRequest().authenticated().
and().formLogin().loginPage("/login").permitAll().
and().logout().invalidateHttpSession(true).clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.permitAll();
}
}
来自registration.html的相关代码片段:
<form th:action="@{/registration}" method="post" th:object="${user}">
<div class="form-group">
<label class="control-label" for="firstName">First name</label> <input
id="firstName" class="form-control" th:field="*{firstName}"
required autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="lastName">Last name</label> <input
id="lastName" class="form-control" th:field="*{lastName}"
required autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="account">Account</label> <input
id="account" class="form-control" th:field="*{account}" required
autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="password">Password</label> <input
id="password" class="form-control" type="password"
th:field="*{password}" required autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="role">Role</label>
<select class="form-control" th:field="*{role}" id="role">
<option th:each="role: ${roles}" th:value="${role}" th:text="${role.name}"></option>
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success">Register</button>
<span>Already registered? <a href="/" th:href="@{/login}">Login
here</a></span>
</div>
</form>
问题:每当我尝试创建具有所选角色的用户时,都会出现以下错误:
字段“角色”上的对象“用户”中的字段错误:拒绝值 [com.example.demo.model.Role@6e32df30];代码 [typeMismatch.user.role,typeMismatch.role,typeMismatch.com.example.demo.model.Role,typeMismatch]; 参数 [org.springframework.context.support.DefaultMessageSourceResolvable: 代码 [user.role,role]; 论据 []; 默认消息[角色]];默认消息 [无法将类型“java.lang.String”的属性值转换为属性“角色”所需的类型“com.example.demo.model.Role”;嵌套异常是 org.springframework.core.convert.ConversionFailedException: 无法从类型 [java.lang.String] 转换为值 'com.example.demo.model.Role@6e32df30' 的类型 [java.lang.Long];嵌套异常是 java.lang.NumberFormatException:对于输入字符串:“com.example.demo.model.
所以,我想我的代码应该做的是使用我们从表单 (${role}) 中获得的 Role 值,并将其应用于 User.java 中的 Role 变量,在关系中连接它们。相反,似乎发生的是,它不是从表单中获取角色值,而是从表单中获取“com.example.demo.model.Role@[random id]”的字符串值。
我对 Spring Boot 和 Thymeleaf 还是很陌生。有谁知道是什么问题?我已经尝试了几个小时来查找这个确切问题的解决方案,但我仍然找不到任何对我有帮助的东西。提前致谢。
解决方案
好的,我环顾四周,终于自己找到了解决方案。原来我必须通过 th:value="${role.id}" 而不是 "${role}"。这是我所做的更改:
用户注册控制器.java:
package com.example.demo.web;
<imports>
@Controller
@RequestMapping("/registration")
public class UserRegistrationController {
private UserService userService;
public UserRegistrationController(UserService userService) {
super();
this.userService = userService;
}
@Autowired
RoleRepository roleRepository;
@GetMapping
public String showRegistrationForm(Model model, User user) {
model.addAttribute("roles", roleRepository.findAll());
return "registration";
}
@PostMapping
public String registerUserAccount(@Valid @ModelAttribute("user") User user, BindingResult result) {
userService.saveUser(user);
return "redirect:/registration?success";
}
}
来自registration.html的相关代码片段:
<form th:action="@{/registration}" method="post" th:object="${user}">
<div class="form-group">
<label class="control-label" for="firstName">First name</label> <input
id="firstName" class="form-control" th:field="*{firstName}"
required autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="lastName">Last name</label> <input
id="lastName" class="form-control" th:field="*{lastName}"
required autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="account">Account</label> <input
id="account" class="form-control" th:field="*{account}" required
autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="password">Password</label> <input
id="password" class="form-control" type="password"
th:field="*{password}" required autofocus="autofocus" />
</div>
<div class="form-group">
<label class="control-label" for="role">Role</label>
<select class="form-control" th:field="*{role}" id="role">
<option th:each="role: ${roles}" th:value="${role.id}" th:text="${role.name}"></option>
</select>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success">Register</button>
<span>Already registered? <a href="/" th:href="@{/login}">Login
here</a></span>
</div>
</form>
希望这可以帮助任何同样困惑的人。