Hibernate: невозможно обновить до нового значения, если в поле присутствует какое-либо значение - PullRequest
0 голосов
/ 21 января 2020

Я не могу обновить значение поля до нового значения, если уже есть значение . В противном случае, если значение отсутствует, обновление работает нормально.

Есть ли что-то, что нам нужно выполнить дополнительно, чтобы выполнить обновление, если для поля есть какое-то значение. И я также не вижу никаких ошибок.

Я использую Hibernate 5.1 и PostgreSQL

EntityClass

@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();
    }

1 Ответ

0 голосов
/ 22 января 2020

Очень неясный поток вызовов при вопросе.
Мое предложение в следующий раз просто опишите точно, шаг за шагом, что вы вызываете в своем приложении.
Похоже, вы написали это в обратном порядке.

Пока я вижу некоторые глупые ошибки в коде.
Трудно понять, является ли это причиной неудачи. Однако вы можете попробовать и посмотреть результат.

Первое место:

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(), если вы позже вызовете commit для транзакции. transactoin.commit() сделает это автоматически.

Я не мог понять, почему была выполнена следующая проверка: index % 100? Если это обязательно, пожалуйста, напишите комментарий о том, почему его следует использовать там. Кроме того, не знаю, почему вы используете IntRange класс для перебора списка? Вы не используете методы из IntRange. Вы можете использовать поток для перебора списка.

Гораздо лучше будет заменить update() на saveOrUpdate(). Это должно быть более логично с функциональностью, которую вы хотите предоставить -> если не найден соответствующий объект, просто сохраните его В противном случае обновите его.

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();
        }
    }
}

Третье место:

Трудно понять ваш поток из ваших фрагментов кода. Если я понял из вашего вопроса, что у вас есть проблема, когда ваша организация уже установила какое-либо значение.

Вы можете проверить, есть ли у этого элемента какой-либо элемент или сохранен в БД. Если да, вы можете использовать org.springframework.beans.BeanUtils.copyProperties (source, target) .

После обновления данных сохранить их обратно в БД.

...