我开始向您展示我的情况。
这是我的父对象:
@Entity
@Table(name="cart")
public class Cart implements Serializable{
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
@Column(name="id")
private Integer id;
@OneToMany(mappedBy="cart", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<CartItem> cartItems;
...
}
这是我的子对象:
@Entity
@Table(name="cart_item")
public class CartItem implements Serializable{
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
@Column(name="id")
private Integer id;
@ManyToOne
@JoinColumn(name="cart_id", nullable=false)
private Cart cart;
...
}
您可以看到数据库,在表 cart_item (子对象)中,字段 cart_id 具有指向字段 id 的外键表购物车(父对象)中的“ strong”。
这是我保存对象的方式:
1)有一个 restController 可以读取JSON对象:
@RestController
@RequestMapping(value = "rest/cart")
public class CartRestController {
@Autowired
private CartService cartService;
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.CREATED)
public void create(@RequestBody CartDto cartDto) {
cartService.create(cartDto);
}
}
2)这是 CartService ,它只是一个界面:
public interface CartService {
void create(CartDto cartDto);
}
这是CartService的实现:
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class CartServiceImpl implements CartService {
@Autowired
private CartDao cartDao;
@Override
public void create(CartDto cartDto) {
cartDao.create(cartDto);
}
}
CartDao 只是另一个界面,我仅向您展示其实现:
@Repository
public class CartDaoImpl implements CartDao {
@Autowired
private SessionFactory sessionFactory;
// in this method I save the parent and its children
@Override
public void create(CartDto cartDto) {
Cart cart = new Cart();
List<CartItem> cartItems = new ArrayList<>();
cartDto.getCartItems().stream().forEach(cartItemDto ->{
//here I fill the CartItem objects;
CartItem cartItem = new CartItem();
...
cartItem.setCart(cart);
cartItems.add(cartItem);
});
cart.setCartItems(cartItems);
sessionFactory.getCurrentSession().save(cart);
}
}
当我尝试保存新的购物车及其 cart_item 时,出现此错误:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/webstore] threw
exception [Request processing failed; nested exception is
org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException: Object of
class
[com.depasmatte.webstore.domain.CartItem] with identifier [7]: optimistic locking failed;
nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect) :
[com.depasmatte.webstore.domain.CartItem#7]] with root cause
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction
(or unsaved-value mapping was incorrect) : [com.depasmatte.webstore.domain.CartItem#7]
我认为该错误取决于以下事实:当休眠尝试保存购物车的 cart_item , id 还不存在!
在镜头中保存父对象及其子对象的正确方法是什么? 谢谢
答案 0 :(得分:5)
这是您应该遵循的规则列表,以便能够一次存储父实体及其子实体:
PERSIST
(也可以使用CascadeType.ALL
)映射问题:
@Column(name="id")
cartItems
私有 List
实现,因此永远不要直接通过setter来更改它private List<CartItem> cartItems = new ArrayList<>();
@ManyToOne(optional = false)
内使用nullable = false
代替@JoinColumn
fetch = FetchType.LAZY
来收藏最好使用辅助方法来设置关系。例如。类Cart
应具有以下方法:
public void addCartItem(CartItem item){
cartItems.add(item);
item.setCart(this);
}
设计问题:
save
的样板答案 1 :(得分:3)
对于双向关系,如下所示:
这是示例代码:
public class Parent {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "fk_parent")
private List<Child> children;
}
public class Child {
@ManyToOne
@JoinColumn(name = "fk_parent")
private Parent parent;
}
答案 2 :(得分:1)
您是否检查过此帖子? Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
您可能会在此问题中找到一个合适的答案,我认为您的问题出在您的getCurrentSession上,即使您使用会话是因为休眠不是线程安全的,会话仍然是轻量级对象和非线程安全的对象。你应该从这里挖东西。
实际上,当一个线程/会话将一个对象保存在数据库中时,如果另一个线程/会话尝试执行相同的操作,则将引发此类错误,因为id已经存在,因此该操作是不可能的。
干杯!
答案 3 :(得分:1)
确保您的方法是事务性的。您可以在方法签名的顶部使用@Transactional
注释使方法事务性。
答案 4 :(得分:0)
对于这个问题非常重要的讨论中,显然缺少一件重要的事情,即谁拥有这种关系。 您将mapedBy放在父实体中,这意味着此关系的所有者转到子实体,他必须通过显式设置属性来填充此关系,否则将不会建立此关系。将JoinColumn注释放在Parent之上,这将确保关系所有者为父,当父实体自动保存时,他将建立此关系
答案 5 :(得分:0)
由于使用了服务,我知道这与问题并不直接相关,但是当我遇到类似问题时,谷歌将我带到了这里。就我而言,我使用的是Spring JPA存储库。确保使用 @ org.springframework.transaction.annotation.Transactional
注释存储库界面