Hibernate выбрать для обновления - PullRequest
0 голосов
/ 22 ноября 2018

Я немного озадачен механизмом выбора для обновления в Spring 4 и Hibernate.Я хотел бы сериализовать доступ к записям заданий в базе данных mySQL, вызывая select-for-update и помечая задания в работе, устанавливая значение (например, здесь называемое «count»).

  1. НАЧАЛО
  2. ВЫБРАТЬ * ИЗ РАБОТЫ, ГДЕ СЧЕТ <1 ДЛЯ ОБНОВЛЕНИЯ;// только 1 строка в БД для анализа, предложение LIMIT понадобится позже </li>
  3. ОБНОВЛЕНИЕ ЗАДАНИЯ SET count = count + 1;
  4. COMMIT

В коде Java я хочусломаться, когда считать> 0 и принять следующую работу.В командной строке это работает нормально.Пока первая передача не завершена, другая транзакция ожидает завершения первой транзакции.После этого, 2-й выбор правильно доставляет счет 1 вместо 0 (вместо «0», который был значением до начала 2-го выбора).Нет, так хорошо.

В Hibernate и Spring код останавливается (правильно) и продолжается, как только блокируемый tx будет зафиксирован.Красиво и правильно.

К сожалению, результатом является не «1» (как ожидалось), а старое значение «0».

Что не так?Я ожидал того же поведения, что и в командной строке?

POM:

<springframework.version>4.2.3.RELEASE</springframework.version>
<mysql.connector.version>5.1.31</mysql.connector.version>
<hibernate.version>4.3.11.Final</hibernate.version>

Объект:

@Entity
@Table(name = TableNames.Job)
public class Job implements Serializable, DataModel {

private static final long serialVersionUID = -5552161667860673186L;

private Integer id;
private Integer count;

public Job() {
    super();
}

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(unique = true, nullable = false)
public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public Integer getCount() {
    return count;
}

public void setCount(Integer count) {
    this.count = count;
}

}

Конфиг:

@Configuration
@EnableTransactionManagement
@EnableScheduling
@ComponentScan({ "blabla", "blabla"})
@PropertySource(value = { "classpath:application.properties" })
public class ContextConfiguration {

private static Logger LOG = LoggerFactory.getLogger(ContextConfiguration.class);

@Autowired
private Environment env;

@Bean
public DataSource dataSource() {

    return new JndiDataSourceLookup().getDataSource("java:comp/env/jdbc/blabblabbla");
}

@Bean
public LocalSessionFactoryBean sessionFactory() {
    LOG.debug("getSesionFactory !!!!! ******");
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] { "blabla" });
    sessionFactory.setHibernateProperties(hibernateProperties());

    return sessionFactory;
}

@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(s);
    return txManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
}

Properties hibernateProperties() {
    System.out.println("Hibernate properties gelesen !!!!! ******");
    return new Properties() {
        private static final long serialVersionUID = 2082799704578665372L;

        {
            setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
            setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
            setProperty("hibernate.globally_quoted_identifiers", "true");
        }
    };
}

Тестовый код:

@Transactional
public void doTest() {

    List<Job> jobs = session.createQuery("From " + tableName + " where id=1").setLockMode(tableName, LockMode.UPGRADE_NOWAIT).list();

    if (jobs.size() == 1) {

        Job job = jobs.get(0);

        session.flush();
        session.refresh(job);
        session.flush();
        System.out.println(job.getCount() + "->" + (job.getCount() + 1));

        job.setCount(job.getCount() + 1);
        session.update(job);
        session.flush();
    }

Имена таблиц (только для понимания)

public interface TableNames {
    public static final String Job = "Job";
//Blabblablabla
}

Как вы можете видеть, я пытался убедиться в отсутствии проблем с кэшированием, сбрасываясумасшедший, но я не помогаю.Метод test () вызывается через службу таймера весны каждые 2 миллисекунды.Как только я вызываю команду select-for-update в командной строке, вывод останавливается и ждет, пока я не обновлю счетчик до «0» и не напишу «COMMIT» в командной строке.Но объект задания в java не обновился, это 1323432 или то, что когда-либо было раньше - несмотря на то, что он ожидает точно в позиции оператора выбора для обновления в коде java - как в командной строке.

Есть идеи, в чем проблема?

Спасибо всем !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...