休眠选择更新

时间:2018-11-22 12:10:22

标签: spring hibernate transactions select-for-update

我对Spring 4和Hibernate的select-for-update机制有些困惑。我想通过调用select-for-update并通过设置值(例如在此称为“ count”)标记工作中的作业来序列化对mySQL数据库中作业条目的访问。

  1. 开始
  2. SELECT * FROM JOB WHERE count <1进行更新; //数据库中只有1行用于分析,稍后需要LIMIT子句
  3. 更新作业设置计数=计数+1;
  4. 提交

在Java代码中,当count> 0时我想中断并执行下一个作业。在命令行中,这可以正常工作。只要第一个交易未完成,其他交易就一直等到第一个交易完成。此后,第二个选择正确传递计数1而不是0(而不是“ 0”,它是第二个选择开始之前的值)。不远,很好。

在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
}

如您所见,我试图通过疯狂刷新来确保不存在缓存问题,但我没有帮助。每隔2毫秒通过spring计时器服务调用一次test()方法。一旦我在命令行中调用“选择更新”,输出就会停止并等待,直到我更新计数为“ 0”并在命令行中写入“ COMMIT”。但是Java中的job对象尚未更新,它是1323432或以前的版本-尽管它恰好在java代码中select-for-update语句的位置等待-就像在命令行中一样。

任何人的想法,问题出在哪里?

谢谢大家!

0 个答案:

没有答案