我正在使用auditing capabilities of Spring Data并且有一个类似于此的类:
@Entity
@Audited
@EntityListeners(AuditingEntityListener.class)
@Table(name="Student")
public class Student {
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
private Long id;
@CreatedBy
private String createdBy;
@CreatedDate
private Date createdDate;
@LastModifiedBy
private String lastModifiedBy;
@LastModifiedDate
private Date lastModifiedDate;
...
现在,我相信我已经配置了审计,因为我可以看到在更新域对象时createdBy,createdDate,lastModifiedBy和lastModifiedDate都获得了正确的值 .
但是,我的问题是,当我更新对象时,我将丢失createdBy和createdDate的值 . 所以,当我第一次创建对象时,我有四个值,但是当我更新它时,createdBy和createdDate都无效!我也在使用Hibernate envers来保存域对象的历史记录 .
你知道为什么我会这样做吗?当我更新域对象时,为什么createdBy和createdDate为空?
更新:要回答@ m-deinum 's questions: Yes spring data JPA is configured correctly - everything else works fine - I really wouldn' t喜欢发布配置,因为当你完成它需要很大的空间 .
我的AuditorAwareImpl是这样的
@Component
public class AuditorAwareImpl implements AuditorAware {
Logger logger = Logger.getLogger(AuditorAwareImpl.class);
@Autowired
ProfileService profileService;
@Override
public String getCurrentAuditor() {
return profileService.getMyUsername();
}
}
最后,这是我的更新控制器实现:
@Autowired
private StudentFormValidator validator;
@Autowired
private StudentRepository studentRep;
@RequestMapping(value="/edit/{id}", method=RequestMethod.POST)
public String updateFromForm(
@PathVariable("id")Long id,
@Valid Student student, BindingResult result,
final RedirectAttributes redirectAttributes) {
Student s = studentRep.secureFind(id);
if(student == null || s == null) {
throw new ResourceNotFoundException();
}
validator.validate(student, result);
if (result.hasErrors()) {
return "students/form";
}
student.setId(id);
student.setSchool(profileService.getMySchool());
redirectAttributes.addFlashAttribute("message", "Επιτυχής προσθήκη!");
studentRep.save(student);
return "redirect:/students/list";
}
更新2:请查看更新的版本
@RequestMapping(value="/edit/{id}", method=RequestMethod.GET)
public ModelAndView editForm(@PathVariable("id")Long id) {
ModelAndView mav = new ModelAndView("students/form");
Student student = studentRep.secureFind(id);
if(student == null) {
throw new ResourceNotFoundException();
}
mav.getModelMap().addAttribute(student);
mav.getModelMap().addAttribute("genders", GenderEnum.values());
mav.getModelMap().addAttribute("studentTypes", StudEnum.values());
return mav;
}
@RequestMapping(value="/edit/{id}", method=RequestMethod.POST)
public String updateFromForm(
@PathVariable("id")Long id,
@Valid @ModelAttribute Student student, BindingResult result,
final RedirectAttributes redirectAttributes, SessionStatus status) {
Student s = studentRep.secureFind(id);
if(student == null || s == null) {
throw new ResourceNotFoundException();
}
if (result.hasErrors()) {
return "students/form";
}
//student.setId(id);
student.setSchool(profileService.getMySchool());
studentRep.save(student);
redirectAttributes.addFlashAttribute("message", "Επιτυχής προσθήκη!");
status.setComplete();
return "redirect:/students/list";
}
当我做更新时,这仍然会使createdBy和createdDate字段变空:(
此外,它没有得到学校的 Value (由于它与当前正在编辑的用户有关,因此不包含在我的表格中)所以我需要从SecurityContext再次获取它...我做错了什么?
更新3:供参考,不要在评论中遗漏:主要问题是我需要将@SessionAttributes注释包含在我的控制器中 .
2 回答
你的(@)Controller类中的方法效率不高 . 您不希望(手动)检索对象并将所有字段,关系等复制到其中 . 在具有复杂对象的旁边,您将更快或更改遇到大麻烦 .
你想要的是你的第一个方法(用于显示表单的GET)检索用户并使用
@SessionAttributes
将其存储在会话中 . 接下来,您需要@InitBinder
带注释的方法在WebDataBinder
上设置验证器,以便spring执行验证 . 这将使您的updateFromForm
方法变得干净整洁 .您需要将
SessionStatus
属性添加到方法并标记处理完成,以便Spring可以从会话中清除模型 .这样你就不必复制对象等了,Spring将完成所有的升降,你的所有场/关系都将被正确设置 .
使用 @Column 注释的 updatable 属性,如下所示 .
这将在更新操作上保留创建日期 .