我正在我的网络应用程序中设置客户端购物车。在添加购物车类和他的服务之前一切都很好。现在,当我尝试启动 Spring 应用程序时,会显示此错误:
Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.myBookstoreProject.domain.security.UserRole.role -> com.myBookstoreProject.domain.security.Role
我寻找解决方案,但发现我的应用程序实体存在问题。解决方案是将 (cascade=CascadeType.ALL) 添加到导致错误的实体。但我的类(class)已经有了它,并且在购物车类(class)之前一切都很好。
用户类别:
@Entity public class User implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", nullable = false, updatable = false) private Long id; private String username; private String password; private String firstName; private String lastName; @Column(name = "email", nullable = false, updatable = false) private String email; private String phone; private boolean enabled = true; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JsonIgnore private Set<UserRole> userRoles = new HashSet<>(); @OneToMany(cascade = CascadeType.ALL, mappedBy = "user") private List<UserShipping> userShippingList; @OneToMany(cascade = CascadeType.ALL, mappedBy = "user") private List<UserPayment> userPaymentList; @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") private ShoppingCart shoppingCart; // getters and setters.. }
角色
@Entity public class Role { @Id private int roleId; private String name; @OneToMany(mappedBy = "role", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private Set<UserRole> userRoles = new HashSet<UserRole>(); // getters and setters.. }
UserRole 类:
@Entity @Table(name = "user_role") public class UserRole { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long userRoleId; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "role_id") private Role role; // getters and setters.. }
购物车:
@Entity public class ShoppingCart { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private BigDecimal GrandTotal; @OneToMany(mappedBy="shoppingCart", cascade=CascadeType.ALL, fetch=FetchType.LAZY) @JsonIgnore private List<CartItem> cartItemList; @OneToOne(cascade=CascadeType.ALL) private User user; // getters and setters... }
购物车服务实现:
@Service public class ShoppingCartServiceImpl implements ShoppingCartService { @Autowired private CartItemService cartItemService; @Autowired private ShoppingCartRepository shoppingCartRepository; @Override public ShoppingCart updateShoppingCart(ShoppingCart shoppingCart) { BigDecimal cartTotal = new BigDecimal(0); List<CartItem> cartItemList = cartItemService.findByShoppingCart(shoppingCart); for (CartItem cartItem : cartItemList) { if (cartItem.getBook().getInStockNumber() > 0) { cartItemService.updateCartItem(cartItem); cartTotal = cartTotal.add(cartItem.getSubtotal()); } } shoppingCart.setGrandTotal(cartTotal); shoppingCartRepository.save(shoppingCart); return shoppingCart; } }
用户服务实现:
在这个类方法中,我添加了“@Transactional”和 5 行购物车,然后出现错误
@Override
@Transactional
public User createUser(User user, Set<UserRole> userRoles) throws Exception {
User localUser = userRepository.findByUsername(user.getUsername());
if (localUser != null) {
LOG.info("user {} already exists. Nothing will be done.", user.getUsername());
} else {
for (UserRole ur : userRoles) {
roleRepository.save(ur.getRole());
}
user.getUserRoles().addAll(userRoles);
ShoppingCart shoppingCart = new ShoppingCart(); // 1
shoppingCart.setUser(user); // 2
user.setShoppingCart(shoppingCart); // 3
user.setUserShippingList(new ArrayList<UserShipping>()); //4
user.setUserPaymentList(new ArrayList<UserPayment>()); // 5
localUser = userRepository.save(user);
}
return localUser;
}
此错误会终止 Spring 应用程序,并且仅在 MySql 中创建表而不添加行。
编辑 1: 当我尝试向我的应用程序添加新用户时会出现问题。这是我的引导主类:
@SpringBootApplication
public class BookstoreProjectApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(BookstoreProjectApplication.class, args);
}
@Autowired
private UserService userService;
@Override
public void run(String... args) throws Exception {
User user1 = new User();
user1.setFirstName("New");
user1.setLastName("User");
user1.setUsername("j");
user1.setPassword(SecurityUtility.passwordEncoder().encode("p"));
user1.setEmail("newUser@gmail.com");
Set<UserRole> userRoles = new HashSet<>();
Role role1 = new Role();
role1.setRoleId(1);
role1.setName("ROLE_USER");
userRoles.add(new UserRole(user1, role1));
userService.createUser(user1, userRoles);
}
}
如果我注释方法主体(run),服务器运行得很好,直到创建新用户,然后出现错误。
最佳答案
您正在坚持 roles
来自您的userRole
然后将它们分配给用户,但在保存它们后,您不会将持久实体分配给角色,因此 roles
在userRole
与持久化的不再相同,也没有生成的 id
。当您保存一个实体,然后将其或父实体作为值添加到另一个实体并且没有完全级联时,您将添加一个不同的对象。这意味着,使用 save 的返回对象并将其重新分配给您保存的对象,然后应该没问题,或者在各处使用级联并仅保存 1 个对象。
TLDR; userRoles
'role
与 Role
不一样数据库中的实体。
编辑1:
更改Set<UserRole> userRoles
至List<UserRole> userRoles
(否则你必须将其转换大约 100 次,因为你无法在遍历 Set 时替换它的值)然后替换
for (UserRole ur : userRoles) {
roleRepository.save(ur.getRole());
}
与
for (int i = 0; i < userRoles.size(); i++) {
userRoles.get(i).setRole(roleRepository.save(userRoles.get(i).getRole())
}
关于java - 如何修复 ' org.hibernate.TransientPropertyValueException'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57851900/