我对Spring 4和Hibernate的select-for-update机制有些困惑。我想通过调用select-for-update并通过设置值(例如在此称为“ count”)标记工作中的作业来序列化对mySQL数据库中作业条目的访问。
在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语句的位置等待-就像在命令行中一样。
任何人的想法,问题出在哪里?
谢谢大家!