Java 如何修复';org.hibernate.TransientPropertyValueException';?
我正在我的web应用程序中设置客户端购物车。在添加购物车类和他的服务之前,一切正常。现在,当我尝试启动Spring应用程序时,会显示以下错误:Java 如何修复';org.hibernate.TransientPropertyValueException';?,java,spring,hibernate,jpa,thymeleaf,Java,Spring,Hibernate,Jpa,Thymeleaf,我正在我的web应用程序中设置客户端购物车。在添加购物车类和他的服务之前,一切正常。现在,当我尝试启动Spring应用程序时,会显示以下错误: Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.myBookstoreProject.d
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 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... }
@实体 公共类购物车{ @身份证 @GeneratedValue(策略=GenerationType.AUTO) 私人长id; 私人总收入; @OneToMany(mappedBy=“shoppingCart”,cascade=CascadeType.ALL,fetch=FetchType.LAZY) @杰索尼奥雷 私人名单; @OneToOne(级联=级联类型.ALL) 私人用户; //接球手和接球手。。。 }
- 购物车服务实施:
@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; } }
@服务 公共类ShoppingCartServiceImpl实现ShoppingCartService{ @自动连线 私人CartItemService CartItemService; @自动连线 私人购物车存储库购物车存储库; @凌驾 公共购物车更新购物车(购物车购物车){ BigDecimal cartTotal=新的BigDecimal(0); List cartItemList=cartItemService.findByShoppingCart(shoppingCart); 对于(CartItem CartItem:cartItemList){ 如果(cartItem.getBook().getInStockNumber()>0){ cartItemService.UpdateArtItem(cartItem); cartTotal=cartTotal.add(cartItem.getSubtotal()); } } shoppingCart.setGrandTotal(cartTotal); shoppingCartRepository.save(shoppingCart); 返回购物车; } }
- 用户服务实现:
@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;
}
@覆盖
@交易的
公共用户createUser(用户用户,设置用户角色)引发异常{
User localUser=userRepository.findByUsername(User.getUsername());
if(localUser!=null){
LOG.info(“用户{}已存在。将不执行任何操作。”,user.getUsername());
}否则{
for(UserRole-ur:userRoles){
roleRepository.save(ur.getRole());
}
user.getUserRoles().addAll(userRoles);
ShoppingCart ShoppingCart=新建ShoppingCart();//1
shoppingCart.setUser(user);//2
user.setShoppingCart(shoppingCart);//3
user.setUserShippingList(新ArrayList());//4
user.setUserPaymentList(新的ArrayList());//5
localUser=userRepository.save(用户);
}
返回本地用户;
}
此错误终止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);
}
}
@springboot应用程序
公共类BookstoreProjectApplication实现CommandLineRunner{
公共静态void main(字符串[]args){
run(BookstoreProjectApplication.class,args);
}
@自动连线
私人用户服务;
@凌驾
公共无效运行(字符串…参数)引发异常{
用户user1=新用户();
user1.setFirstName(“新”);
user1.setLastName(“用户”);
user1.setUsername(“j”);
user1.setPassword(SecurityUtility.passwordEncoder().encode(“p”));
user1.setEmail(“newUser@gmail.com");
Set userRoles=new HashSet();
Role role1=新角色();
角色1.setRoleId(1);
角色1.setName(“角色用户”);
添加(新的UserRole(user1,role1));
createUser(user1,userRoles);
}
}
如果我对方法体(run)进行注释,则在创建新用户之前服务器运行良好,然后出现错误。您正在从
userRole
持久化角色,然后将其分配给用户,但保存后不会将持久化的实体分配给角色,因此,userRole
中的角色
不再与持久化的角色相同,也没有生成的id
。当您保存一个实体,然后将其或其父实体作为值添加到另一个实体,并且没有完全级联时,您添加的是另一个对象。这意味着,使用“保存”中的返回对象,并将其重新分配给保存的对象,然后该对象应该可以正常工作,或者使用“到处级联”并仅保存1个对象
TLDR<代码>用户角色
“角色
与数据库中的角色
实体不同
编辑1:
将Set userRoles
更改为List userRoles
(否则您必须将其转换100次,因为您无法在遍历集合时替换集合的值),然后替换
for (UserRole ur : userRoles) {
roleRepository.save(ur.getRole());
}
与
for(int i=0;i
您是否尝试从您的用户字段上的购物车中删除级联类型?是的,但仍然是相同的错误:原因:org.hibernate.TransientPropertyValueException:对象引用未保存的临时实例-在刷新之前保存临时实例:com.myBookstoreProject.domain.security.UserRole.role->com.myBookstoreProject.domain.security.Role
太好了!这个解决方案似乎工作正常。只有一个问题:在回答的第一行中,您说:“保存后您不会将持久化实体分配给角色,因此userRole中的角色不再与持久化实体相同。”。为什么在添加购物车类之前,应用程序会运行
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())
}