Вопрос

Я разрабатываю двойную учетную систему бухгалтерского учета, и мне нужно вставлять запись записи без пробелов в последовательном идентификаторе. Поскольку вся доступ к базе данных произойдет через веб-приложение, я забочусь о генерации ID с использованием синскризованной статической переменной:

import org.hibernate.*;

public class JournalService {    
    private static Object journalLock = new Object();    
    private Session session;

    public JournalService(Session session) {
        this.session = session;
    }

    public void insertJournalEntry(JournalEntry journalEntry) {
        Set<PostEntry> entries = journalEntry.getEntries();

        double total = 0;

        for (PostEntry entry : entries) {
            total += entry.getAmount();
        }

        if(total != 0)
            throw new InvalidParameterException("Journal entry is invalid. The sum of all entries must be zero.");

        Criteria criteria = session.createCriteria(PostEntry.class);
        criteria.setMaxResults(1);
        criteria.addOrder(Order.desc("id"));
        //here I add some other criteria
        synchronized(journalLock) {            
            PostEntry lastEntry = criteria.uniqueResult();
            long currentId = lastEntry.getId();

            for (PostEntry entry : entries) {
                entry.setId(currentId++)
                session.save(entry);
            }            
            session.save(journalEntry);
        }
    }
}

Через несколько слов эта служба имеет всю службу, привязанную к текущему HTTPREQUEST и управляется весенним контейнером, кроме того, я убедиться, что вся транзакция передается в конце запроса. Синхронизированный блок позаботится о любом параллелизме, поэтому нет никаких пробелов в последовательности ID. Большая проблема здесь - добавленная поверхность доступа к базе данных для выбора последней вставленной записи, которая соответствует определенным критериям. Я не хочу, чтобы это произошло, поэтому я предполагаю, что решение здесь использует кэш, который будет держать последнюю вставленную запись в первый раз его выбранный, поэтому для генерации идентификатора не требуется доступ к базе данных. Мой вопрос: есть ли какая-то из коробки с гибернатом способа решения этого? Я новичок в зимующий и слышал о запросе кеша, но я не уверен, как его использовать. Я не хочу, чтобы кэш удержал каждое величину, которое я хранят в этом сервисе, мне просто нужно, чтобы сохранить последнюю вставленную запись, которая соответствует определенным критериям. Например, если я выполнял пять вставок, в которых два соответствует равным критериям «X», а остальные три соответствует критериям «y», кэш будет иметь только два хранимых объекта (последний вставленный объект, который соответствует каждому критериям). Я мог бы легко реализовать это сам, но я бы предпочел использовать решение, которое интегрируется с Hibernate API.

Это было полезно?

Решение

Кэширование лучше подходит для хранения часто доступов Но редко модифицированные объекты. Отказ Что это не то, что вы пытаетесь сделать. Вы можете использовать сериализуемую транзакцию, которая предотвращает потерянные обновления и несовместимые чтения Что вы пытаетесь избежать. Но вы должны помнить его над головой.

// Hibernate Transaction isolation level settings
// Serializable isolation level
hibernate.connection.isolation=8

Вот идет что Sessionfactory. API говорит

Поведение SecurityFactory контролируется свойствами, поставляемыми при времени конфигурации. Отказ Эти свойства определяются на окружающей среде.

Как обходной путь, вы можете настроить два отчетных SecurityFactory, где один из них является сериализацией, как показано выше.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top