我发现当我坚持它时我仍然可以操作该实体,例如。在当前Block的priorId中设置前一个Block的id,这是代码。
ArticleService.class
public void createArticle(Article article, List<Block> blocks) throws Exception {
...
//check blocks
if (!blocks.isEmpty()) {
article.setBlocks(blocks);
articleDAO.create(article);
//here is the question, after persisting I can still operate it.
article.setBlocks(BlockUtil.setPriorId(blocks));
} else {
throw new Exception("blocks must be set");
}
...
}
ArticleDAO.class
public void create(Article article) {
em.persist(article);
}
BlockUtil.class
public static List<Block> setPriorId(List<Block> blocks) {
List<Block> resultBlocks = new ArrayList<>();
if (!blocks.isEmpty()) {
resultBlocks.add(blocks.get(0));
for (int i = 1; i < blocks.size(); i++) {
blocks.get(i).setPriorId(blocks.get(i - 1).getId());
resultBlocks.add(blocks.get(i));
}
}
return resultBlocks;
}
所以当我坚持一个实体时,我很困惑。我认为它没有保存到数据库中,对吗?也许它仍然由EntityManager管理,但为什么我可以获得id?非常感谢你!
答案 0 :(得分:1)
EntityManager会记住附加到会话的所有实体(无论您是从数据库中读取实体还是保留新实体)。任何这些附加实体的任何更改都会在事务结束时更新到数据库中。基本上,在事务结束时(或者更具体地说,任何时候发生“刷新”),对每个连接的实体执行“脏检查”。任何“脏”实体(在Java运行时具有不同状态的实体)比数据库中存储的内容导致对数据库的更新。
答案 1 :(得分:1)
在JPA中,您的实体有两种状态:
当持久实体时,它会进入托管状态。例如,当您合并时。参数中的对象保持分离,但合并功能中的返回对象为托管。
托管状态意味着您的EntityManager
将对象保留在其持久性上下文中。当您提交事务时,它会将其上下文中的每个对象存储到数据库中。事务中托管对象的每次更改都将最终存储到数据库中。
如果需要在提交之前将对象存储到数据库中,可以通过flush
方法完成。但要考虑所有的共同点。
答案 2 :(得分:0)
实体的生命周期
通过使用EntityManager实例将操作应用于实体来管理实体实例,
(EntityManager em
)。实体实例处于以下四种状态之一:new,managed,detached或
删除:
持久实体 - 保存到数据库
通过调用persist
方法或通过级联持久化操作来管理新实体实例并因此保持持久性,这些操作是从关系注释中设置了cascade = PERSIST或cascade = ALL元素的相关实体调用的。
为什么级联实体?
在关系数据库中,表中的外键列引用另一个数据库表中的主键。如果您要从表'Customers'中删除主要'4233455'的实体(DB记录),那么表CustomerData中的实体,引用其外键字段CustomerId (指'4233455'),指的是不再存在的实体。
为确保关系数据库中表之间的引用关系一致,表级联的概念是 定义。这意味着当与持久化操作相关联的事务完成时('commit'),实体的数据将存储到数据库中。如果实体已经被管理,则忽略持久化操作,尽管持久化操作将级联到具有级联元素的相关实体 在关系注释中设置为PERSIST或ALL。
如果在已删除的实体实例上调用persist,则该实体将被管理。
如果实体是分离的,则持久化将抛出IllegalArgumentException
,否则事务提交将失败(如果持久性配置指定,则可以产生事务回滚)。
持久性缓存
关系数据库缓存内存中的实体。根据使用的关系数据库,可能需要em-operation em.flush()
以确保数据已保存到磁盘(或内存数据库的永久存储)。