我正在Web应用程序中设置客户端购物车。在添加Shopping Cart类和他的服务之前,一切都还好。现在,当我尝试启动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)添加到导致错误的实体。但是我的课程已经有了,在购物车课程开始之前一切都很好。
用户类别:
@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);
}
}
如果我注释方法主体(运行),则服务器运行得很好,直到应创建新用户为止,然后出现错误。
答案 0 :(得分:1)
您要从roles
中持久保存userRole
,然后将其分配给用户,但是在保存后,您不会将持久实体分配给角色,因此roles
userRole
中的不再与持久化的相同,并且也没有生成的id
。当您保存一个实体,然后将其或父级作为值添加到另一个实体并且没有完全级联时,您将添加另一个对象。这意味着,使用保存时返回的对象并将其重新分配给您保存的对象,然后应该没问题,或者在所有地方使用级联,仅保存1个对象。
TLDR; userRoles
'role
与数据库中的Role
实体不同。
编辑1:
将Set<UserRole> userRoles
更改为List<UserRole> userRoles
(否则必须转换100次,因为遍历aSet时无法替换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())
}