I've recently tried to implement Spring Security into my web store project to distinguish between single users. Websites are working properly except there is one issue which I can't track to resolve. I have object called Customer
within User
class. Customer
object has fields like id
, balance
, etc., and User
has OneToOne
relationship to Customer
, so I can have single object for credentials and foreign key to specifics of user - his first name, last name, balance, owned products, etc.
I also have Product
class which has ManyToOne
relationship with Customer
. It has its' own id
, productCost
, etc.
I'm using Spring MVC to take care of proper URL dispatching. When some action is taken, I'm using @AuthenticationPrincipal
annotation to get currently logged Customer
(through foreign key in User
) and modify data regarding Customer
linked with that foreign key.
When I modify Customer
data through @AuthenticationPrincipal
in controller, changes are immediate and they show up on website. But when I try to modify data through some DAO, for example by searching for Customer
through id
or try to get Customer
that owns Product
from Product
getter ( ManyToOne
has reference to owning Customer
), changes are not immediate. Database updates itself immediately and properly, like in first case, but collections in code and website state are not changed until I logout and login again - that's when data is updated. I suspect it may be due to fact that updating UserDetails
updates data directly for currently logged user but then - how may I achieve same effect for Customer
found by id
?
Snippets of code: 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;
Piece of controller code:
@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 I use UserDetails
object in controller and I am also using DAO for Customer
used as foreign key in UserDetails
. Using UserDetails
directly updates data and everything works fine, using DAO doesn't make changes until I logout and login.
as far as i understand your changes are only commited when you log out. just try to synchronize and commit any modification at the right time and it would be safer that you manage sessions and transactions at the same time so you don't get any sort of incoherence when you do that. then tell me about the results.
Check whether CTRL+F5 in your browser (force cache clearance) updates your data similarly to logging out and back in. If so, it's a question of cached information. (this and (3) may occur at the same time)
Alternatively... or perhaps complementarly... your data fetch reqeust may be called before the database update/commit operation is completed. If so, it should become evident if you run distinct update and show routines. ie turn A into B, then into C, and you'd get something like B when you're expecting C... A instead of B... etc.
Lastly, depending on how you set up your back end, it is possible that you only populate whatever form you use for the front end exactly once, instead of dynamically querying the database whenever you access that form.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.