我有一个测试,创建一个实体,更新它并检查更新后上次修改日期时间是否增加。我使用 JdbcClient 在 PostgreSQL 上执行以下查询:
INSERT INTO entity (id, modified_on) VALUES (1, CURRENT_TIMESTAMP) RETURNING *;
UPDATE entity SET modified_on=CURRENT_TIMESTAMP WHERE id=1 RETURNING *;
问题是
modified_on
没有增加。
这是一个显示问题的简化测试:
@Autowired
private JdbcClient jdbcClient;
@Test
void test() {
var time1 = (java.sql.Timestamp) jdbcClient.sql("SELECT CURRENT_TIMESTAMP").query().singleValue();
System.out.println(time1);
var time2 = (java.sql.Timestamp) jdbcClient.sql("SELECT CURRENT_TIMESTAMP").query().singleValue();
System.out.println(time2);
assertThat(time2).isAfter(time1);
}
失败,因为
time1
等于 time2
。
我想
JdbcClient
应该立即提交查询。但似乎它在单个事务中执行它们,这就是时间相同的原因。
我当然可以使用
statement_timestamp()
,它会修复测试。但我需要CURRENT_TIMESTAMP
。是否可以在查询之间强制提交?
使测试通过的一种方法(虽然有点人为)是引入一个服务类,为每个调用创建一个新事务。
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
@Service
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class TimeService {
private final JdbcClient jdbcClient;
public TimeService(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public Timestamp getCurrentTimestamp() {
return (java.sql.Timestamp) jdbcClient.sql("SELECT CURRENT_TIMESTAMP").query().singleValue();
}
}
请注意,必须使用
@Import(TimeService.class)
将此类导入到测试类中
测试:
@Autowired
TimeService timeService;
@Test
void test() throws InterruptedException {
Timestamp time1 = timeService.getCurrentTimestamp();
Timestamp time2 = timeService.getCurrentTimestamp();
assertThat(time2.getTime()).isGreaterThan(time1.getTime());
}