如何持久化实体类中的数据并结合数据传输对象?
Posted
技术标签:
【中文标题】如何持久化实体类中的数据并结合数据传输对象?【英文标题】:How to persist data from the entity class and combined with data transfer object? 【发布时间】:2020-09-09 21:45:17 【问题描述】:我正在开发一项身份验证功能,但在持久化实体类中的数据时遇到了问题。我能够从数据传输对象访问密码哈希和用户名,但无法从数据库中的用户类中查看电子邮件、名字、姓氏或电话号码。下面的照片是我注册新用户时发生的情况的示例。可以看到有 4 列没有数据。
当我添加 newUser
时,我使用了一个看起来像这样的 processRegistrationForm 方法...
@PostMapping("/register")
public String processRegistrationForm(@ModelAttribute @Valid RegisterFormDTO registerFormDTO,
Errors errors, HttpServletRequest request,
Model model)
// a few conditionals that I removed for brevity
User newUser = new User(registerFormDTO.getUsername(), registerFormDTO.getPassword(), registerFormDTO.getFirstName(), registerFormDTO.getLastName(), registerFormDTO.getEmail(), registerFormDTO.getPhoneNumber());
userRepository.save(newUser);
setUserInSession(request.getSession(), newUser);
return "redirect:";
registerFromDTO
public class RegisterFormDTO extends LoginFormDTO
private String verifyPassword;
private String firstName;
private String lastName;
private String email;
private String phoneNumber;
//getters and setters.
LoginFormDTO
public class LoginFormDTO
@NotNull
@NotBlank
@Size(min = 3, max = 20, message = "Invalid username. Must be between 3 and 30 characters.")
private String username;
@NotNull
@NotBlank
@Size(min = 5, max = 20, message = "Invalid password. Must be between 5 and 30 characters.")
private String password;
//getters and setters
用户类..
@Entity
public class User extends AbstractEntity
@NotBlank
private String username;
@NotBlank
private String pwHash;
//@Column(name = "first_name")
private String firstName;
//@Column(name = "last_name")
private String lastName;
//@Column(name = "email")
private String email;
//@Column(name = "phone_number")
private String phoneNumber;
public User()
private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
public User(String username, String password, String firstName, String lastName, String email, String phoneNumber)
this.username =username;
this.pwHash = encoder.encode(password);
this.firstName =firstName;
this.lastName = lastName;
this.email = email;
this.phoneNumber = phoneNumber;
public boolean isMatchingPassword(String password)
return encoder.matches(password, pwHash);
//getters and setters
最后但并非最不重要的是我的注册表单视图
<form method="post">
<div class="form-group">
<label>Username
<input class="form-control" th:field="$registerFormDTO.username" />
</label>
<p class="error" th:errors="$registerFormDTO.username"></p>
</div>
<div class="form-group">
<label>Password
<input class="form-control" th:field="$registerFormDTO.password" type="password" />
</label>
<p class="error" th:errors="$registerFormDTO.password"></p>
</div>
<div class="form-group">
<label>Verify Password
<input class="form-control" th:field="$registerFormDTO.verifyPassword" type="password" />
</label>
</div>
<div class="form-group">
<label>First Name
<input class="form-control" th:field="$registerFormDTO.firstName" type="firstName" />
</label>
</div>
<div class="form-group">
<label>Last Name
<input class="form-control" th:field="$registerFormDTO.lastName" type="lastName" />
</label>
</div>
<input type="submit" class="btn btn-primary" value="Register" />
</form>
【问题讨论】:
RegisterFormDTO
在processRegistrationForm
方法中是否包含来自表单视图的有效值?
@mslowiak 我有两个正在验证的字段,没有出现任何错误。我需要向其他字段添加额外的验证注释吗?
我只是询问在调用该方法后RegisterFromDTO
实例中是否存在任何值。尤其是如果registerFormDTO.getUsername()
有一些值或者它本身就是一个空值
@mslowiak RegisterFormDTO 中存在三个值:verifyPassword
、username
和 password
。
所以看起来你以LoginFormDTO
作为模型而不是RegisterFromDTO
呈现注册表...
【参考方案1】:
您可以使用 MapStruct 从 DTO 映射到模型。
例如:
@Mapper
public interface EmployeeMapper
@Mappings(
@Mapping(target="employeeId", source="entity.id"),
@Mapping(target="employeeName", source="entity.name")
)
EmployeeDTO employeeToEmployeeDTO(Employee entity);
@Mappings(
@Mapping(target="id", source="dto.employeeId"),
@Mapping(target="name", source="dto.employeeName")
)
Employee employeeDTOtoEmployee(EmployeeDTO dto);
“Quick Guide to MapStruct”有更多信息。
【讨论】:
请不要说“...更多在这里。”使用更具描述性的东西。以下页面帮助解释:参见“Don’t use “click here” and other common hyperlink mistakes”、“Don't use "click here" as link text”和“Links and Hypertext - Link Text and Appearance”【参考方案2】:该表单需要包含一些内容以保存在registerFormDTO
中收集的数据。第一个是:
1.在表单标签中,添加th:action="@/register"
和th:object="registerFormDTO"
2. 在输入标签中,将type="text"
添加到每个输入字段,并将其中type="password"
、type="firstName"
等更改为id="password"
和id="firstName"
等。
做这些事情可以让 Thymeleaf 连接并保存收集到的数据。
这是完整的代码。
<form th:action="@/register" th:object="$registerFormDTO" method="post">
<div class="form-group">
<label>Username
<input class="form-control" type="text" th:field="$registerFormDTO.username" id="username" />
</label>
<p class="error" th:errors="$registerFormDTO.username"></p>
</div>
<div class="form-group">
<label>Password
<input class="form-control" type="text" th:field="$registerFormDTO.password" id="password" />
</label>
<p class="error" th:errors="$registerFormDTO.password"></p>
</div>
<div class="form-group">
<label>Verify Password
<input class="form-control" type="text" th:field="$registerFormDTO.verifyPassword" id="password" />
</label>
</div>
<div class="form-group">
<label>First Name
<input class="form-control" type="text" th:field="$registerFormDTO.firstName" id="firstName" />
</label>
</div>
<div class="form-group">
<label>Last Name
<input class="form-control" type="text" th:field="$registerFormDTO.lastName" id="lastName" />
</label>
</div>
<div class="form-group">
<label>Email
<input class="form-control" type="text" th:field="$registerFormDTO.email" id="email" />
</label>
</div>
<div class="form-group">
<label>Phone Number
<input class="form-control" type="text" th:field="$registerFormDTO.phoneNumber" id="phoneNumber" />
</label>
</div>
<input type="submit" class="btn btn-primary" value="Register" />
</form>
【讨论】:
以上是关于如何持久化实体类中的数据并结合数据传输对象?的主要内容,如果未能解决你的问题,请参考以下文章
Symfony2/Doctrine:如何从实体类中持久化一个实体?