Java Spring JPA 审计空 createdBy
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19090258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring JPA Auditing empty createdBy
提问by Serafeim
I am using the auditing capabilities of Spring Dataand have a class similar to this:
我正在使用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; ...
Now, I believe I have configured auditing fine because I can see that createdBy, createdDate, lastModifiedBy and lastModifiedDate all are getting the correct values when I update the domain objects.
现在,我相信我已经很好地配置了审计,因为当我更新域对象时,我可以看到 createdBy、createdDate、lastModifiedBy 和 lastModifiedDate 都获得了正确的值。
However, my problem is that when I update an object I am losing the values of createdBy and createdDate. So, when I first create the object I have all four values, but when I update it createdBy and createdDate are nullified ! I am also using the Hibernate envers to keep a history of the domain objects.
但是,我的问题是,当我更新对象时,我丢失了 createdBy 和 createdDate 的值。因此,当我第一次创建对象时,我拥有所有四个值,但是当我更新它时 createdBy 和 createdDate 被取消了!我还使用 Hibernate envers 来保存域对象的历史记录。
Do you know why do I get this behavior ? Why do createdBy and createdDate are empty when I update the domain object ?
你知道我为什么会有这种行为吗?为什么在更新域对象时 createdBy 和 createdDate 为空?
Update: To answer @m-deinum 's questions: Yes spring data JPA is configured correctly - everything else works fine - I really wouldn't like to post the configuration because as you udnerstand it will need a lot of space.
更新:回答@m-deinum 的问题:是的,spring 数据 JPA 配置正确-其他一切正常-我真的不想发布配置,因为在您看来它需要很多空间。
My AuditorAwareImpl is this
我的 AuditorAwareImpl 是这个
@Component public class AuditorAwareImpl implements AuditorAware { Logger logger = Logger.getLogger(AuditorAwareImpl.class); @Autowired ProfileService profileService; @Override public String getCurrentAuditor() { return profileService.getMyUsername(); } }
Finally, here's my update controller implementation:
最后,这是我的更新控制器实现:
@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"; }
Update 2: Please take a look at a newer version
更新 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"; }
This stillleaves empty the createdBy and createdDate fields when I do an update :(
当我进行更新时,这仍然使 createdBy 和 createdDate 字段为空:(
Also it does not get the School value (which is not contained in my form because it is related to the user currently editing) so I need to get it again from the SecurityContext... Have I done anything wrong ?
它也没有得到 School 值(它没有包含在我的表单中,因为它与当前编辑的用户有关)所以我需要从 SecurityContext 再次获取它......我做错了什么吗?
Update 3: For reference and to not miss it in the comments: The main problem was that I needed to include the @SessionAttributes annotation to my controller.
更新 3:供参考,不要在评论中错过:主要问题是我需要将 @SessionAttributes 注释包含到我的控制器中。
采纳答案by M. Deinum
Your method in your (@)Controller class is not that efficient. You don't want to (manually) retrieve the object and copy all the fields, relationships etc. over to it. Next to that with complex objects you will sooner or alter run into big trouble.
您的 (@)Controller 类中的方法效率不高。您不想(手动)检索对象并将所有字段、关系等复制到它。除了复杂的对象,你会很快或改变遇到大麻烦。
What you want is on your first method (the GET for showing the form) retrieve the user and store it in the session using @SessionAttributes
. Next you want an @InitBinder
annotated method to set your validator on the WebDataBinder
so that spring will do the validation. This will leave your updateFromForm
method nice and clean.
您想要的是在您的第一个方法(用于显示表单的 GET)中检索用户并将其存储在会话中使用@SessionAttributes
. 接下来,您需要一个带@InitBinder
注释的方法来设置验证器,WebDataBinder
以便 spring 进行验证。这将使您的updateFromForm
方法干净整洁。
@Controller
@RequestMapping("/edit/{id}")
@SessionAttributes("student")
public EditStudentController
@Autowired
private StudentFormValidator validator;
@Autowired
private StudentRepository studentRep;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
@RequestMapping(method=RequestMethod.GET)
public String showUpdateForm(Model model) {
model.addObject("student", studentRep.secureFind(id));
return "students/form";
}
@RequestMapping(method=RequestMethod.POST)
public String public String updateFromForm(@Valid @ModelAttribute Student student, BindingResult result, RedirectAttributes redirectAttributes, SessionStatus status) {
// Optionally you could check the ids if they are the same.
if (result.hasErrors()) {
return "students/form";
}
redirectAttributes.addFlashAttribute("message", "?p?t???? p??s????!");
studentRep.save(student);
status.setComplete(); // Will remove the student from the session
return "redirect:/students/list";
}
}
You will need to add the SessionStatus
attribute to the method and mark the processing complete, so that Spring can cleanup your model from the session.
您需要将SessionStatus
属性添加到该方法并将处理标记为完成,以便 Spring 可以从会话中清除您的模型。
This way you don't have to copy around objects, etc. and Spring will do all the heave lifting and all your fields/relations will be properly set.
通过这种方式,您不必复制对象等,Spring 将完成所有举重工作,并且您的所有字段/关系都将被正确设置。
回答by Maz
Use updatableattribute of @Columnannotation like below.
使用@Column注释的可更新属性,如下所示。
@Column(name = "created_date", updatable = false)
private Date createdDate;
This will retain the created date on update operation.
这将保留更新操作的创建日期。