【问题标题】:Hibernate: Not able to update to a new value if some value is present for a field休眠:如果某个字段存在某个值,则无法更新为新值
【发布时间】:2020-05-07 23:19:03
【问题描述】:

如果已经存在值,我无法将字段值更新为新值。否则,如果不存在任何值,则更新工作正常。

如果该字段存在某些值,我们是否需要执行其他任何操作来执行更新。而且我也没有看到任何错误。

我正在使用 Hibernate 5.1 和 PostgreSQL

实体类

@Setter
@ToString
@Builder(toBuilder = true)
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PACKAGE)
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@Table(name = "TableA")
public class TableA {

    @Id
    @Column(name = "id")
    private String id;

    @Column(name = "columnA")
    private String columnA;

    @Column(name = "created_date")
    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    private java.util.Calendar createdDate;

    @Column(name = "updated_date")
    @UpdateTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    private java.util.Calendar updatedDate;

    @Column(name = "columnB")
    private java.util.Calendar columnB;

    @Column(name = "columC")
    private String columC;
}


批量更新方法:

   public void updateBatchTableAData(List<TableA> tableAList) {
        Session session = sessionFactory.openSession();
        try {
            log.info("Executing batch source Data");
            Transaction transaction = session.beginTransaction();
            IntStream.range(0, tableAList.size())
                     .filter(index -> tableAList.get(index) != null)
                     .forEach(index -> {
                         session.update(tableAList.get(index));
                         if (index % 100 == 0) {
                             session.flush();
                             session.clear();
                         }
                     });
            session.flush();
            session.clear();
            transaction.commit();
        } catch (Exception e) {
            log.error(
                    "Exception occurred while saving Batch TableA Data to the DB.", e);
        }
        session.close();
    }

获取内容方法

public List getTableAData() {
        Session session = sessionFactory.openSession();
        try {
            Criteria criteria = session.createCriteria(TableA.class);
            return criteria.list();
        } catch (Exception e) {
            throw new RuntimeException("Exception occurred while trying to fetch TableA data", e);
        }
    }

更新方法


   public void executeMethod(){
        List<TableA> tableAList = new ArrayList();
        getTableAData().forEach(data -> {
            TableA tableA = (TableA) data;
            tableA.setColumnB(null);
            tableA.setColumnC("newmodified_value");
            tableAList.add(tableA);
        });
        updateBatchTableAData(tableAList);
    }

SessionFactory

    @Provides
    @Singleton
    public SessionFactory getPostgresqlSessionFactory() {
        Configuration configuration = new Configuration();
        configuration.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, CURRENT_SESSION_PROPERTY_VALUE);
        configuration.setProperty(Environment.DRIVER, SetupConstants.POSTGRES_DRIVER);
        configuration.setProperty(Environment.URL,
                getDbURL());
        configuration.setProperty(Environment.USER, getUsername());
        configuration.setProperty(Environment.PASS, getPassword());
        configuration.setProperty(Environment.RELEASE_CONNECTIONS, RELEASE_CONNECTIONS_VALUE);
        configuration.setProperty(Environment.DIALECT, POSTGRESQL_DIALECT);
        configuration.setProperty(Environment.SHOW_SQL, SHOW_SQL_VALUE);
        configuration.setProperty(Environment.HBM2DDL_AUTO, HBM2DDL_AUTO_VALUE);
        configuration.setProperty(Environment.AUTOCOMMIT, "true");
        configuration.setProperty(Environment.STATEMENT_BATCH_SIZE, String.valueOf(BATCH_SIZE));
        configuration.setProperty(Environment.ORDER_INSERTS, ORDER_INSERTS_VALUE);
        configuration.setProperty(Environment.ORDER_UPDATES, "true");
        configuration.setProperty(Environment.BATCH_VERSIONED_DATA, "true");
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(configuration.getProperties())
                .build();
        MetadataSources metadataSources = new MetadataSources(serviceRegistry);
        Reflections entityPackageReflections = new Reflections("PACKAGE_NAME");
        entityPackageReflections.getTypesAnnotatedWith(Entity.class).forEach(metadataSources::addAnnotatedClass);
        Metadata metadata = metadataSources.getMetadataBuilder().build();
        return metadata.getSessionFactoryBuilder().build();
    }

【问题讨论】:

  • 您是否尝试过调试您的代码执行?另外,你有没有从控制器调用你的 service/dao 方法?
  • 是的。我调试了。我能够在 session.flush 之前看到 TableA 的更新值。我正在使用 guice 注入器调用这些方法。对我来说,如果特定字段没有任何值,更新工作正常。仅当已经存在某些值时,才不会发生更新
  • 你的问题解决了吗?

标签: java postgresql hibernate hibernate-criteria


【解决方案1】:

在某个问题上的呼叫流程非常不清楚。
下次我的建议只是逐步准确地描述您在应用程序中调用的内容。
看起来你是按相反的顺序写的。

目前,我在代码中看到了一些愚蠢的错误。
很难理解这是否是失败的原因。不过,你可以试试看效果。

第一名:

public List<TableA> getTableAData() {
    List<TableA> list = new ArrayLsit<>();
    Session session = sessionFactory.openSession();
    try {
       Criteria criteria = session.createCriteria(TableA.class);
       list = criteria.list();
    } catch (Exception e) {
       throw new RuntimeException("Exception occurred while trying to fetch TableA data", e);
    } finally {
      if (session.isOpen()) {
          session.close();
      }
    }
    return list;
}

第二名:

如果您稍后为事务调用提交,则无需调用session.flush()。 transactoin.commit() 会自动完成。

我不明白为什么要进行以下检查:index % 100? 如果它是强制性的,请写下为什么应该在那里使用它的评论。 另外,不知道为什么要使用IntRange 类来遍历列表?您没有使用来自IntRange 的任何方法。您可以使用流来遍历列表。

用saveOrUpdate() 替换update() 会更好。对于您要提供的功能,它应该更合乎逻辑->如果找不到合适的实体,请保存它。否则,更新它。

public void updateBatchTableAData(List<TableA> tableAList) {
    Session session = sessionFactory.openSession();
    try {
        log.info("Executing batch source Data");
        session.beginTransaction();
        tableAList.stream()
                 .filter(Objects::nonNull)
                 .forEach(element -> session.saveOrUpdate(element));
        session.getTransaction.commit();
    } catch (Exception e) {
        log.error("Exception occurred while saving Batch TableA Data to the DB.", e);
        session.getTransaction().rollback();
    } finally {
        if (session.isOpen()) {
            session.close();
        }
    }
}

第三名:

很难从您的代码 sn-ps 中理解您的流程。如果我从您的问题中了解到当您的实体已经设置任何值时您遇到问题。

您可以检查此元素是否已经有任何项目或保存到数据库。如果是,您可以使用org.springframework.beans.BeanUtils.copyProperties(source, target)。

更新数据后将其保存回数据库。

【讨论】:

    猜你喜欢
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2020-04-10
    • 2022-11-23
    相关资源
    最近更新 更多