spring-security 数据在表中更改后不会立即更新

x6h2sr28  于 2022-11-11  发布在  Spring
关注(0)|答案(2)|浏览(237)

我最近尝试在我的Web商店项目中实现Spring Security来区分单个用户。网站工作正常,除了一个问题我无法跟踪解决。我在User类中有一个名为Customer的对象。Customer对象有idbalance等字段。而UserCustomer具有OneToOne关系,因此我可以使用单个对象作为凭据,并使用外键来指定用户细节-他的名字、姓氏、余额、拥有的产品等。
我也有Product类,它和CustomerManyToOne关系,它有自己的idproductCost等等。
我使用Spring MVC来处理正确的URL调度。当采取一些操作时,我使用@AuthenticationPrincipal注解来获取当前记录的Customer(通过User中的外键),并修改与该外键链接的Customer相关的数据。
当我通过控制器中的@AuthenticationPrincipal修改Customer数据时,更改是立即的,并且它们会显示在网站上。但是当我试图通过一些DAO修改数据时,例如,通过id搜索Customer,或者尝试从Product getter获取拥有ProductCustomerManyToOne引用了所有Customer),更改不会立即发生。数据库会立即并正确地更新自身,就像第一种情况一样,但是代码和网站状态中的集合不会改变直到我注销并再次登录-这是数据更新的时候。我怀疑这可能是由于更新UserDetails直接为当前登录的用户更新数据的事实,但然后-我如何才能实现由id找到的Customer相同的效果?
代码片段:Users.java:

@Entity
@Table(name="users")
public class Users {

    @Id
    @Column(name="username")
    private String username;

    @Column(name="password")
    private String password;

    @Column(name="enabled")
    private boolean isActive;

    @OneToMany(mappedBy="user")
    private Set<Authorities> authorities;

    @OneToOne
    @JoinColumn(name="customer_id")
    private Customer customer;

Product.java:

@Entity
@Table(name="product")
public class Product {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="name")
    private String productName;

    @Column(name="description")
    private String productDescription;

    @Column(name="category")
    private String productCategory;

    @Column(name="cost")
    private int productCost;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="owner_id")
    private Customer productOwner;

Customer.java:

@Entity
@Table(name="customer")
public class Customer {

    //Class fields

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="balance")
    private int balance;

    @Column(name="first_name")
    private String firstName;

    @Column(name="last_name")
    private String lastName;

    @Column(name="email")
    private String email;

    @OneToMany(mappedBy="productOwner", fetch=FetchType.EAGER)
    private List<Product> ownedProducts;

块控制器代码:

@Autowired
    CustomerService customerService;

    @Autowired
    ProductService productService;
/*(...)*/
@GetMapping("/showOffer/{offerId}")
    public String getOffer(@PathVariable int offerId, Model theModel, @AuthenticationPrincipal MyUserDetails user) {
        Product retrievedProduct = productService.findById(offerId);
        if (user.getCustomer().getBalance() >= retrievedProduct.getProductCost())
        {
            Customer retrievedProductOwner = retrievedProduct.getProductOwner();
/* This is where changes aren't applied immediately and I need to logout and login to process them. */
            retrievedProductOwner.setBalance(1000);
/* This is where changes are immediately shown and Java collections are updated: */
            user.getCustomer().setBalance(user.getCustomer().getBalance()-retrievedProduct.getProductCost());
/* Code below is an attempt to force immediate changes by updating collections directly from database - but that approach doesn't work */
            productService.delete(retrievedProduct.getId());
            retrievedProduct.getProductOwner().getOwnedProducts().clear();
            retrievedProduct.getProductOwner().setOwnedProducts(productService.listOwnerProducts(retrievedProduct.getProductOwner()));
        }
        else {
            System.out.println("Insufficient funds!");
        }
        return "redirect:/home";

TL:DR我在控制器中使用UserDetails对象,并且我还在UserDetails中使用Customer的DAO作为外键。使用UserDetails直接更新数据,一切正常,使用DAO直到我注销并登录后才进行更改。x1c 0d1x

esbemjvw

esbemjvw1#

据我所知,您的更改仅在您注销时提交。请尝试同步并在正确的时间提交任何修改,同时管理会话和事务会更安全,这样做时就不会出现任何不一致。然后告诉我结果。

kx7yvsdv

kx7yvsdv2#

1.检查浏览器中的CTRL+F5(强制清除缓存)是否像注销和重新登录一样更新数据。如果是,则是缓存信息的问题。(这和(3)可能同时发生)
1.或者......或者是补充......您的数据提取请求可能会在数据库更新/提交操作完成之前被调用。如果是这样的话,如果您运行不同的更新和显示例程,这应该会变得很明显。例如,将A转换为B,然后转换为C,当您期望C...... A而不是B......等等时,您会得到类似B的结果。
1.最后,根据您设置后端的方式,您可能只填充一次用于前端的任何表单,而不是在每次访问该表单时动态查询数据库。

相关问题