Spring JPA审核为空已创建 [英] Spring JPA Auditing empty createdBy

查看:106
本文介绍了Spring JPA审核为空已创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Spring Data的审计功能,并具有类似于以下的类:

I am using the auditing capabilities of Spring Data and have a class similar to this:


@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当我更新域对象时,所有这些都获得了正确的值。

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的值。因此,当我第一次创建对象时,我具有所有四个值,但是当我对其进行更新时,createdBy和createdDate均无效!我还使用Hibernate envers来保留域对象的历史记录。

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为空?

Do you know why do I get this behavior ? Why do createdBy and createdDate are empty when I update the domain object ?

Update :要回答@ m-deinum的问题:是的,春天数据JPA配置正确-其他一切正常-我真的不愿意发布配置,因为当您了解它时将需要很多空间。

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.

我的AuditorAwareImpl是这个

My AuditorAwareImpl is this


@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";  
}  

更新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";  
     }  

当我执行更新时,此 still 留空createdBy和createdDate字段:(

This still leaves empty the createdBy and createdDate fields when I do an update :(

它也不会获得School值(该值不包含在我的表单中,因为它与当前正在编辑的用户有关),因此我需要再次从SecurityContext ...我做错了什么吗?

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 ?

更新3 :仅供参考,不要在评论中错过:主要问题是我需要在控制器中包括@SessionAttributes注释。

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.

推荐答案

您的(@)Controller类中的方法并非如此效率(您不希望(手动)检索该对象并将所有字段,关系等复制到该对象上),再加上复杂的对象,您早晚或会遇到麻烦。

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.

第一种方法(显示表单的GET)上想要的是检索用户并将其存储在会话中,使用 @SessionAttribu tes 。接下来,您要使用 @InitBinder 批注的方法在 WebDataBinder 上设置验证器,以便spring进行验证。这将使您的 updateFromForm 方法保持整洁。

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.

@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";  
    }
}  

您将需要添加 SessionStatus 属性的方法并标记处理完成,以便Spring可以从会话中清理模型。

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.

这样,您可以不必在对象等周围复制。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 JPA审核为空已创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆