在执行存储库保存方法之前,百里香表单中的对象被保存到数据库中

问题描述 投票:0回答:1

我有一个带有 thymeleaf 前端、Spring 后端和 mariadb 数据库的全栈应用程序。当我尝试通过 thymeleaf 表单更新对象时,出现了奇怪的问题。 对象的类如下所示(简化):

@Entity
@Table(name = "[tenants]")
@ApiModel( value = "Tenant", description = "Tenants resource representation" )
public class Tenant implements Serializable {

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "[tenant_id]")
    @ApiModelProperty( value = "tenantId", required = false )
    private long tenantId;
    
    @OneToMany(mappedBy = "tenant", fetch = FetchType.EAGER)
    @JsonIgnoreProperties("tenant")
    private List<Car> cars = new ArrayList<>();
    
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @Column(name = "[rent_start]")
    @ApiModelProperty( value = "rentStart", required = true )
    @NotNull(message = "Rent start is required")
    private Date rentStart;

    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @Column(name = "[rent_end]")
    @ApiModelProperty( value = "rentEnd", required = true )
    @NotNull(message = "Valid to is required")
    private Date rentEnd;
    
}

Car 类如下所示:

@Entity
@Table(name = "[car]")
@ApiModel( value = "Car", description = "Cars resource representation" )
public class Car implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "[car_id]")
    @ApiModelProperty( value = "carId", required = false )
    private long carId;
    
    @ManyToOne
    @JoinColumn(name = "tenant_id", nullable = true)
    @JsonIgnoreProperties("cars")
    private Tenant tenant;

}

在后端有一个 TenantView 类的常见结构,它调用 TenantService,TenantService 调用扩展 CrudRepository 的 TenantRepository。我的问题发生在更新租户时。以下是更新租户时调用的方法:

租户视图:

@RequestMapping(path="/update-tenant", method = RequestMethod.POST)
    public ModelAndView updateTenant(@Valid @ModelAttribute("tenant") Tenant tenant, BindingResult result, HttpServletRequest request, RedirectAttributes redirectAttributes) {
        ModelAndView modelAndView = new ModelAndView();
        ResponseMessage message = null;      
        
        try { 
            tenantService.save(tenant);
            // Neues ModelAndView mit Redirect verwenden, um das POST-Redirect-Get-Pattern umzusetzen
            modelAndView = new ModelAndView("redirect:/view/tenants/all");
            message = new ResponseMessage("message.success.title", "tenant.message.success.update.text", "message.success.color");
            redirectAttributes.addFlashAttribute("message", message);            
            LOGGER.debug("Update tenant was successfully");
            return modelAndView;   
        } catch (SQLException sex) {
            LOGGER.error(sex.getMessage());
            modelAndView = new ModelAndView("redirect:/view/tenants/update-tenant/");
            message = new ResponseMessage("message.error.title", "tenant.message.error.update.sql.text", "message.error.color");
            redirectAttributes.addFlashAttribute("message", message);
            return modelAndView;
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage());            
            modelAndView = new ModelAndView("redirect:/view/tenants/update-tenant/");
            message = new ResponseMessage("message.error.title", "tenant.message.error.update.unkown.text", "message.error.color");
            redirectAttributes.addFlashAttribute("message", message);
            return modelAndView;
        }
}

租户服务实现:

public Tenant save(Tenant tenant) throws SQLException {
        return tenantRepository.save(tenant);
}

TenentRepository:CrudRepository

这是我的问题:我有一个租户租了两辆车(我想这里并不重要),他的rentStart是01-01-2024,rentEnd是12-31-2024。他是这样保存在我的数据库里的。我想将rentStart更新为06-06-2024,rentEnd更新为06-30-2024。我在TenantView的第一行设置了一个断点(ModelAndView modelAndView = new ModelAndView();)。当我现在查看数据库时,新日期(2024 年 6 月 6 日和 2024 年 6 月 30 日)已保存在数据库中。之后代码按预期执行并再次保存。我不知道如何开始在这里搜索问题。我尝试在每种情况下设置断点“tenantRepository.save(tenant);”被调用但没有运气。

关于我和提供的代码的一些信息:我是一名初级开发人员,拥有大约一年的经验。所以我不知道您是否需要更多或不同的信息。我处理的代码是生产代码,因此我无法在这里一对一地发布它,因此我对其进行了修剪并更改了类名称。从我的示例数据来看,这应该不是问题,因为无论哪种方式,结果都是相同的,无论它是否在实际保存到存储库之前保存到数据库中。但在实际代码中,汽车也会根据某些逻辑在服务中进行更新,当租户过早保存时,这些逻辑就会中断。我测试了这个逻辑是否与问题有关并将其注释掉,以便真正的存储库保存方法看起来与提供的方法完全相同。问题依然存在。

我不期望快速解决(也不会抱怨),因为我认为问题存在于更深层次的地方。我想知道是否有人经历过类似的事情,并且知道从哪里以及如何开始寻找问题的原因。

提前非常感谢您!

spring mariadb thymeleaf
1个回答
0
投票

昨天睡觉前(还有什么时候?)我想到了一个想法。

我将 TenantService 中的方法命名为“save”。如果这个名字有问题怎么办?该名称在 TenentRepository 扩展 CrudRepository 中有其固定用途。今天我尝试将该方法重命名为其他名称,它实际上解决了我的问题。 所以我自己得出结论:如果您使用 CrudRepository 中的 save 方法,请不要命名服务方法,其中会发生一些除了调用存储库之外的附加逻辑,只是“保存”,但还有其他东西。

需要注意的是,我使用 Ubuntu 22.04.4 LTS。我的同事使用 MacO。他没有遇到这个问题。

我仍然不知道为什么会发生这种情况。也许比我更熟练的人可以进一步解释。

© www.soinside.com 2019 - 2024. All rights reserved.