【问题标题】:For loop to save data in Hibernate not adding all itemsFor循环在Hibernate中保存数据不添加所有项目
【发布时间】:2018-10-06 00:29:48
【问题描述】:

尝试使用 for 循环使用 hibernate 4.3.11.Final 和 SQLite 方言保存/提交数据com.enigmabridge:hibernate4-sqlite-dialect

当我运行此代码并检查 Sqlite 数据时,我看到它只保存了 1 项(似乎只提交一次),并且一项是我看到的最后一项(我生成的 5 项中)在数据库中。

configureSessionFactory();
Session session = null;
Transaction tx=null;
try {
    session = sessionFactory.openSession();
    SyndEntry entry = null;
    URL feedUrl = new URL(rssUrl);
    SyndFeedInput input = new SyndFeedInput();
    SyndFeed feed = input.build(new XmlReader(feedUrl));
    tx = session.beginTransaction();
    BroadcastItem item = new BroadcastItem();
    for (int i = 0 ; i < 5 ; i++) {
         entry = (SyndEntry) feed.getEntries().get(i);
         item.setMessage(entry.getTitle());
         item.setLinkUrl(entry.getLink());
         session.save(item);
    }
    tx.commit();
} catch (Exception ex) {
  ex.printStackTrace();
  // Rolling back the changes to make the data consistent in case of any failure in between multiple database write operations.
   tx.rollback();
} finally{
  if(session != null) {
      session.close();
  }
}

但是当我在 for 循环中移动 tx = session.beginTransaction(); 时,我得到了

不支持嵌套事务

  1. 我怎样才能完成我想要的(循环 5 次,每次向数据库中添加一个数据项)?
  2. 为什么commit在这里只运行一次?

【问题讨论】:

  • 我知道它可能会令人困惑,但我将其包含在内是因为我理解它的方式是 JDBC 始终存在,在低级别,Hibernate 构建在它之上。我认为 JPA 是一种规范,而 Hibernate 是一种实现(EclipseLink 的方式),我们使用 JPA 注释。不想反驳我的标签会让人感到困惑,只是想指出原因。
  • 你说得对,这个问题是一个休眠问题。但是我的 BroadcastItem 类有 javax.persistence.* 导入。这里的答案为我清除了一切:stackoverflow.com/questions/15040583/…

标签: java database hibernate


【解决方案1】:

当你写作时

    BroadcastItem item = new BroadcastItem();

    for (int i = 0 ; i < 5 ; i++) {
        entry = (SyndEntry) feed.getEntries().get(i);

        item.setMessage(entry.getTitle());
        item.setLinkUrl(entry.getLink());

        session.save(item);
    }

第一次保存(创建)item,在循环的其他时间,保存(更新)item

您只需将您创建的BroadcastItem 放入循环中,如下所示:

    for (int i = 0 ; i < 5 ; i++) {
        entry = (SyndEntry) feed.getEntries().get(i);
        BroadcastItem item = new BroadcastItem();

        item.setMessage(entry.getTitle());
        item.setLinkUrl(entry.getLink());

        session.save(item);
    }

【讨论】:

  • 这行得通,谢谢,但是有没有办法避免每次都创建一个对象?有没有办法一次又一次地回收同一个对象?
  • 不,你不能,因为你的对象被你的 Hibernate 会话“标记为已知”。清楚地看到它的一种方法是,如果您的 item 拥有一个自动递增的 id,这将帮助您更好地理解您的观点。以更直观的方式,将其视为创建一个带有 2 个抽屉的盒子,在其中放置 2 个值,并在每次循环时更改它们:它仍然是同一个盒子,具有不同的值。
  • 是的,这很清楚,还有其他方法可以更有效地做到这一点吗?在任何其他策略上使用流?我问是因为我可能每次都必须插入 5000 个项目。再次感谢。
  • 即使你使用流,你也必须每次都创建一个new BroadcastItem(),很遗憾
  • 好的,谢谢。在 IntelliJ 中运行代码时,它似乎在执行后并没有停止,当我单击 STOP 按钮时,它显示以下消息Process finished with exit code 130 (interrupted by signal 2: SIGINT)session.close() 之后我错过了什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 2013-10-08
  • 1970-01-01
  • 2021-09-22
  • 1970-01-01
  • 2021-02-25
  • 1970-01-01
相关资源
最近更新 更多