EclipseLink - объединяет обновления столбцов, которые не были изменены - PullRequest
0 голосов
/ 08 мая 2018

Я давно использую Eclipselink в своем проекте, но сегодня я столкнулся с проблемой, и не могу ее решить.

Проблема заключается в следующем: сначала я ищу свой объект «Функция» в экземпляре моей программы, затем в другом экземпляре я ищу и изменяю эту же запись (изменил столбцы «Интервал» и «Дата») и сохраняю , После этого в первом случае я изменяю только «Интервал», но в базе данных поле «Дата» было изменено, даже если я не менялся, Eclipselink (в первом случае) генерирует в ОБНОВЛЕНИИ изменение поля » Дата »только потому, что« Функция »первого экземпляра устарела с базой данных, тогда как в это время были внесены изменения в реестр между поиском объекта и его сохранением.

При анализе запросов, сгенерированных в базе данных, я заметил, что Eclipselink генерирует SELECT перед каждым ОБНОВЛЕНИЕМ, но в моем случае мне это не нужно, как я могу заставить Eclipselink добавлять только в ОБНОВЛЕНИЕ поля, в которых были изменения? И не те, которые отличаются от базы данных.

Моя конфигурация Eclipselink:

"javax.persistence.jdbc.driver", "com.mysql.cj.jdbc.Driver"
"javax.persistence.jdbc.url", "jdbc:mysql://{IP}:3306/{USER}?useTimezone=true&serverTimezone=America/Sao_Paulo&autoReconnect=true&zeroDateTimeBehavior=convertToNull"
"javax.persistence.jdbc.user", user
"javax.persistence.jdbc.password", password
"eclipselink.cache.shared.default", "false"
"eclipselink.logging.level", "WARNING"
"eclipselink.query-results-cache", "false"
"eclipselink.refresh", "true"
"eclipselink.weaving", "static"
"connection.autoReconnectForPools", "true"
"connection.autoReconnect", "true"

Код:

Function function = FunctionDAO.getFunctionByName("A");
function.setInterval(0);
...
EntityManager manager = {config};
manager.getTransaction().begin();
manager.merge(function);
manager.getTransaction().commit();
manager.close();

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "function")
public class Function extends ModelAudit implements Serializable {

    private static final long serialVersionUID = 1L;

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

    @Column(name = "interval")
    private Integer interval;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "date")
    private Date date;

    ...
    getters and setters

enter image description here

1 Ответ

0 голосов
/ 09 мая 2018

Мне не нравятся объекты DAO, поскольку эта проблема встречается часто при использовании шаблона поиска / сохранения, и поэтому настоятельно рекомендуется использовать оптимистическую блокировку. Любое количество модификаций могло произойти с момента, когда вы читаете в сущности, до момента, когда вы вызываете функцию сохранения / слияния, и если ваш метод обернут в свою собственную транзакцию и просто использует em.merge (), ваш экземпляр перезаписывает то, что находится в базе данных полностью. Чем дольше вы сохраняете сущность, тем больше вероятность того, что какой-то другой процесс изменил ее и сделал вашу копию данных устаревшей.

Опции:

  1. Используйте некоторую форму оптимистической блокировки. При чтении в сущности, он будет иметь версии, так что когда вы вызываете em.merge, если версия в базе данных опережает то, что вы передаете, это даст исключение, чтобы уведомить вас о потенциальном конфликте.

  2. Реализация методов DAO changeValue, которые обновляют только выбор полей внутри объекта. Например, метод setIntervalByName (имя строки, целочисленный интервал), который может использовать запрос на обновление JPA, чтобы избежать выбора, если вы не хотите читать в объекте, или использовать ту же функциональность, аналогичную вашему методу getFunctionByName.

Использование обоих позволяет передавать объект для сложных изменений, таких как API REST, которые могут сериализовать сущность для запросов на получение / ввод, при этом позволяя оптимизировать, чтобы избежать чтения в графе сущностей для простых изменений в других местах.

...