Hibernate + SQL Server RowVersion (Timestamp) - запросить новое значение после вставки / обновления - PullRequest
0 голосов
/ 25 марта 2020

Столбец rowversion / timestamp в SqlServer является глобальным счетчиком, который увеличивается при каждой вставке и обновлении.

Проблема:

После вставки или обновления свойство гибернации, сопоставленное столбцу версии строк, не обновляется автоматически.

Я хотел бы, чтобы это происходило автоматически = без извлечения этого столбца (или вся модель) после сброса, в каждом месте, где выполняется обновление или вставка.

Мое решение:

На данный момент я попытался извлечь этот столбец сразу после обновления - он не работает если грипп sh происходит не сразу после обновления.

SQL Таблица:

CREATE TABLE [dbo].[Example](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [varchar](50) NOT NULL,
    [description] [varchar](250) NOT NULL,
    [rowversion] [timestamp] NOT NULL,
 CONSTRAINT [PK_Example] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Модель гибернации:

@Entity
@Table(name = "Example")
public class ExampleRow implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private long id;

    @Column(name = "name", nullable = false, length = 50)
    private String name;

    @Column(name = "description", nullable = false, length = 250)
    private String description;

    @Column(name = "rowversion", insertable = false, updatable = false)
    private byte[] rowVersion;

    /* getters & setters */
}

Java:

private ExampleRow fetchFromDataBase(long id) {
    Query<ExampleRow> query = getCurrentSession().createQuery(
            "select row from ExampleRow row where row.id = :id",
            ExampleRow.class);
    query.setParameter("id", id);
    List<ExampleRow> list = query.list();
    ExampleRow singleRowFromDataBase = list.get(0);
    return singleRowFromDataBase;
}

private void printRV(ExampleRow singleRowFromDataBase) {
    for(int i = 0; i < singleRowFromDataBase.getRowVersion().length; i++) {
        System.out.println(i + " => " + singleRowFromDataBase.getRowVersion()[i]);
    }   
}

public ExampleRow edit(long id, String name, String description) {
    ExampleRow singleRowFromDataBase = fetchFromDataBase(id);
    singleRowFromDataBase.setName(name);
    singleRowFromDataBase.setDescription(description);

    // RV before edit
    printRV(singleRowFromDataBase);

    getCurrentSession().merge(singleRowFromDataBase);

    // RV after edit (if flush is set to manual, the rowVersion is still the same - the query is not ran on database yet)
    ExampleRow singleRowFromDataBaseBeforeFlush = fetchFromDataBase(id);
    printRV(singleRowFromDataBaseBeforeFlush);

    getCurrentSession().flush();

    // RV after edit & flush - is updated
    ExampleRow singleRowFromDataBaseAfterFlush = fetchFromDataBase(id);
    printRV(singleRowFromDataBaseAfterFlush);

    // Replace RV value or simply return fresh instance from database...
    singleRowFromDataBase.setRowVersion(singleRowFromDataBaseAfterFlush.getRowVersion());


    return singleRowFromDataBase;
}
...