当我在jPA中使用persist()时发生了什么

时间:2017-05-10 01:41:34

标签: java jpa java-ee

我发现当我坚持它时我仍然可以操作该实体,例如。在当前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?非常感谢你!

3 个答案:

答案 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()以确保数据已保存到磁盘(或内存数据库的永久存储)。