[英]Data doesn't update immediately after changes in tables
我最近尝试将 Spring 安全性实施到我的 web 商店项目中以区分单个用户。 网站运行正常,但有一个问题我无法跟踪解决。 我在User
class 中有一个名为Customer
的 object。 Customer
object 具有id
、 balance
等字段,并且User
与Customer
具有OneToOne
关系,因此我可以拥有单个 object 作为凭据和用户具体信息的外键 - 他的名字,姓氏名称、余额、自有产品等。
我还有Product
class,它与Customer
有ManyToOne
关系。 它有自己的id
、 productCost
等。
我正在使用 Spring MVC 来处理正确的 URL 调度。 当采取某些行动时,我使用@AuthenticationPrincipal
注释获取当前登录的Customer
(通过User
中的外键)并修改有关与该外键链接的Customer
的数据。
当我在 controller 中通过@AuthenticationPrincipal
修改Customer
数据时,更改会立即生效并显示在网站上。 但是,当我尝试通过某些 DAO 修改数据时,例如通过id
搜索Customer
或尝试从Product
getter 获取拥有Product
的Customer
( ManyToOne
已引用拥有Customer
),更改不会立即生效。 数据库会立即正确地自行更新,就像第一种情况一样,但是代码中的 collections 和网站 state 在我注销并再次登录之前不会更改 - 那是数据更新的时候。 我怀疑这可能是因为更新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;
产品.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;
客户.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;
一段controller代码:
@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 我在 controller 中使用UserDetails
object 并且我也在使用 DAO for Customer
作为UserDetails
中的外键。 使用UserDetails
直接更新数据并且一切正常,使用 DAO 在我注销并登录之前不会进行更改。
据我了解,您的更改仅在您注销时才会提交。 只需尝试在正确的时间同步和提交任何修改,同时管理会话和事务会更安全,这样您就不会在执行此操作时出现任何不连贯的情况。 然后告诉我结果。
检查您浏览器中的CTRL+F5(强制清除缓存)是否像注销和重新登录一样更新您的数据。如果是,则为缓存信息的问题。 (这和(3)可能同时发生)
或者......或者可能是互补......您的数据获取请求可能会在数据库更新/提交操作完成之前被调用。 如果是这样,如果您运行不同的更新和显示例程,它应该变得明显。 即,将 A 转换为 B,然后转换为 C,当您期望 C...A 而不是 B... 时,您会得到类似 B 的结果。
最后,根据您设置后端的方式,您可能只填充一次用于前端的任何表单,而不是在访问该表单时动态查询数据库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.