改为使用 H2 进行单元测试。

pull/1/head
ZhouXY108 2024-11-02 00:14:30 +08:00
parent 023bd15f06
commit f5cef8f730
2 changed files with 198 additions and 133 deletions

25
pom.xml
View File

@ -35,28 +35,11 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency> <dependency>
<groupId>com.zaxxer</groupId> <groupId>com.h2database</groupId>
<artifactId>HikariCP</artifactId> <artifactId>h2</artifactId>
<version>4.0.3</version> <version>2.2.224</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.8</version>
<exclusions>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
</exclusions>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -1,98 +1,142 @@
package xyz.zhouxy.jdbc.test; package xyz.zhouxy.jdbc.test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static xyz.zhouxy.jdbc.ParamBuilder.*; import static xyz.zhouxy.jdbc.ParamBuilder.*;
import static xyz.zhouxy.plusone.commons.sql.JdbcSql.IN; import static xyz.zhouxy.plusone.commons.sql.JdbcSql.*;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import javax.sql.DataSource;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import xyz.zhouxy.jdbc.DbRecord; import xyz.zhouxy.jdbc.DbRecord;
import xyz.zhouxy.jdbc.RowMapper; import xyz.zhouxy.jdbc.RowMapper;
import xyz.zhouxy.jdbc.SimpleJdbcTemplate; import xyz.zhouxy.jdbc.SimpleJdbcTemplate;
import xyz.zhouxy.jdbc.SimpleJdbcTemplate.JdbcExecutor; import xyz.zhouxy.jdbc.SimpleJdbcTemplate.JdbcExecutor;
import xyz.zhouxy.plusone.commons.sql.SQL; import xyz.zhouxy.plusone.commons.sql.SQL;
import xyz.zhouxy.plusone.commons.util.ArrayTools;
import xyz.zhouxy.plusone.commons.util.IdGenerator; import xyz.zhouxy.plusone.commons.util.IdGenerator;
import xyz.zhouxy.plusone.commons.util.IdWorker; import xyz.zhouxy.plusone.commons.util.IdWorker;
import xyz.zhouxy.plusone.commons.util.Numbers;
class SimpleJdbcTemplateTests { class SimpleJdbcTemplateTests {
private static final Logger log = LoggerFactory.getLogger(SimpleJdbcTemplateTests.class); private static final Logger log = LoggerFactory.getLogger(SimpleJdbcTemplateTests.class);
private static final DataSource dataSource;
private static final SimpleJdbcTemplate jdbcTemplate; private static final SimpleJdbcTemplate jdbcTemplate;
static { static {
HikariConfig config = new HikariConfig(); JdbcDataSource dataSource = new JdbcDataSource();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/plusone"); dataSource.setURL("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE;MODE=MySQL");
config.setUsername("postgres"); dataSource.setUser("sa");
config.setPassword("zhouxy108"); dataSource.setPassword("");
config.setMaximumPoolSize(8);
config.setConnectionTimeout(1000000);
dataSource = new HikariDataSource(config);
jdbcTemplate = new SimpleJdbcTemplate(dataSource); jdbcTemplate = new SimpleJdbcTemplate(dataSource);
} }
@BeforeAll
static void setUp() throws SQLException {
jdbcTemplate.update("CREATE TABLE sys_account ("
+ "\n" + " id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY"
+ "\n" + " ,username VARCHAR(255) NOT NULL"
+ "\n" + " ,account_status VARCHAR(2) NOT NULL"
+ "\n" + " ,create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"
+ "\n" + " ,created_by BIGINT NOT NULL"
+ "\n" + " ,update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"
+ "\n" + " ,updated_by BIGINT DEFAULT NULL"
+ "\n" + " ,version BIGINT NOT NULL DEFAULT 0"
+ "\n" + ")");
jdbcTemplate.batchUpdate("INSERT INTO sys_account(id, username, account_status, created_by) VALUES (?, ?, ?, ?)", Lists.newArrayList(
buildParams(2L, "zhouxy2", "0", 108L),
buildParams(3L, "zhouxy3", "0", 108L),
buildParams(4L, "zhouxy4", "0", 108L),
buildParams(5L, "zhouxy5", "0", 108L),
buildParams(6L, "zhouxy6", "0", 108L),
buildParams(7L, "zhouxy7", "0", 108L),
buildParams(8L, "zhouxy8", "0", 108L),
buildParams(9L, "zhouxy9", "0", 108L)
), 10);
jdbcTemplate.batchUpdate("INSERT INTO sys_account(id, username, account_status, created_by, create_time, update_time, version) VALUES (?, ?, ?, ?, ?, ?, ?)", Lists.newArrayList(
buildParams(10L, "zhouxy10", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 31),
buildParams(11L, "zhouxy11", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 28),
buildParams(12L, "zhouxy12", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 25),
buildParams(13L, "zhouxy13", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 22),
buildParams(14L, "zhouxy14", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 19),
buildParams(15L, "zhouxy15", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 16),
buildParams(16L, "zhouxy16", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 13),
buildParams(17L, "zhouxy17", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 10),
buildParams(18L, "zhouxy18", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 7),
buildParams(19L, "zhouxy19", "1", 118L, LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 29), 0)
), 10);
jdbcTemplate.update("INSERT INTO sys_account(id, username, account_status, created_by, create_time, updated_by, update_time, version) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
buildParams(20L, "zhouxy20", "2", 118L, LocalDateTime.of(2008, 8, 8, 20, 8), 31L, LocalDateTime.now(), 88L));
}
@Test @Test
void testQuery() throws SQLException { void testQuery() throws SQLException {
Object[] ids = buildParams(22915, 22916, 22917, 22918, 22919, 22920, 22921); Object[] ids = buildParams(5, 9, 13, 14, 17, 20, 108);
String sql = SQL.newJdbcSql() String sql = SQL.newJdbcSql()
.SELECT("*") .SELECT("id", "username", "account_status")
.FROM("test_table") .FROM("sys_account")
.WHERE(IN("id", ids)) .WHERE(IN("id", ids))
.toString(); .toString();
log.info(sql); log.info(sql);
List<DbRecord> rs = jdbcTemplate.queryRecordList(sql, ids); List<DbRecord> rs = jdbcTemplate.queryRecordList(sql, ids);
assertNotNull(rs); for (DbRecord dbRecord : rs) {
for (DbRecord baseEntity : rs) { log.info("{}", dbRecord);
// log.info("id: {}", baseEntity.getValueAsString("id")); // NOSONAR
log.info(baseEntity.toString());
assertTrue(baseEntity.getValueAsString("username").isPresent());
} }
assertEquals(
Lists.newArrayList(
new DbRecord(ImmutableMap.of("id", 5L, "account_status", "0", "username", "zhouxy5")),
new DbRecord(ImmutableMap.of("id", 9L, "account_status", "0", "username", "zhouxy9")),
new DbRecord(ImmutableMap.of("id", 13L, "account_status", "1", "username", "zhouxy13")),
new DbRecord(ImmutableMap.of("id", 14L, "account_status", "1", "username", "zhouxy14")),
new DbRecord(ImmutableMap.of("id", 17L, "account_status", "1", "username", "zhouxy17")),
new DbRecord(ImmutableMap.of("id", 20L, "account_status", "2", "username", "zhouxy20"))
),
rs
);
} }
@Test @Test
void testInsert() throws SQLException { void testInsert() throws SQLException {
List<DbRecord> keys = jdbcTemplate.update( List<Map<String, Object>> keys = jdbcTemplate.update(
"INSERT INTO base_table(status, created_by) VALUES (?, ?)", "INSERT INTO sys_account(username, account_status, created_by) VALUES (?, ?, ?), (?, ?, ?)",
buildParams(1, 886L), buildParams("zhouxy21", "2", 123L, "code22", '2', 456L),
RowMapper.RECORD_MAPPER); RowMapper.HASH_MAP_MAPPER);
log.info("keys: {}", keys); log.info("keys: {}", keys);
assertEquals(1, keys.size()); assertEquals(2, keys.size());
DbRecord result = keys.get(0); for (Map<String,Object> key : keys) {
assertEquals(1, result.getValueAsInt("status").getAsInt()); assertTrue(key.containsKey("id"));
assertEquals(886L, result.getValueAsLong("created_by").getAsLong()); assertInstanceOf(Long.class, key.get("id"));
assertTrue(result.get("id").isPresent()); assertTrue(key.containsKey("create_time"));
assertInstanceOf(Date.class, key.get("create_time"));
}
} }
@Test @Test
void testUpdate() throws SQLException { void testUpdate() throws SQLException {
List<DbRecord> keys = jdbcTemplate.update( List<DbRecord> keys = jdbcTemplate.update(
"UPDATE base_table SET status = ?, version = version + 1, update_time = now(), updated_by = ? WHERE id = ? AND version = ?", "UPDATE sys_account SET account_status = ?, version = version + 1, update_time = now(), updated_by = ? WHERE id = ? AND version = ?",
buildParams(2, 886, 571328822575109L, 0), buildParams("7", 886L, 20L, 88L),
RowMapper.RECORD_MAPPER); RowMapper.RECORD_MAPPER);
assertEquals(1, keys.size());
log.info("keys: {}", keys); log.info("keys: {}", keys);
keys = jdbcTemplate.update(
"UPDATE sys_account SET account_status = ?, version = version + 1, update_time = now(), updated_by = ? WHERE id = ? AND version = ?",
buildParams("-1", 886L, 20L, 88L),
RowMapper.RECORD_MAPPER);
assertEquals(0, keys.size());
} }
final IdWorker idGenerator = IdGenerator.getSnowflakeIdGenerator(0); final IdWorker idGenerator = IdGenerator.getSnowflakeIdGenerator(0);
@ -104,8 +148,8 @@ class SimpleJdbcTemplateTests {
long id = this.idGenerator.nextId(); long id = this.idGenerator.nextId();
try { try {
jdbcTemplate.executeTransaction((JdbcExecutor jdbc) -> { jdbcTemplate.executeTransaction((JdbcExecutor jdbc) -> {
jdbc.update("INSERT INTO base_table (id, created_by, create_time, status) VALUES (?, ?, ?, ?)", jdbc.update("INSERT INTO sys_account (id, username, created_by, create_time, account_status) VALUES (?, ?, ?, ?, ?)",
buildParams(id, 100, LocalDateTime.now(), 0)); buildParams(id, "testTransaction1", 100, LocalDateTime.now(), "55"));
throw new NullPointerException(); throw new NullPointerException();
}); });
} }
@ -113,7 +157,7 @@ class SimpleJdbcTemplateTests {
// ignore // ignore
} }
Optional<Map<String, Object>> first = jdbcTemplate Optional<Map<String, Object>> first = jdbcTemplate
.queryFirst("SELECT * FROM base_table WHERE id = ?", buildParams(id)); .queryFirst("SELECT * FROM sys_account WHERE id = ?", buildParams(id));
log.info("first: {}", first); log.info("first: {}", first);
assertTrue(!first.isPresent()); assertTrue(!first.isPresent());
} }
@ -122,12 +166,12 @@ class SimpleJdbcTemplateTests {
{ {
long id = this.idGenerator.nextId(); long id = this.idGenerator.nextId();
jdbcTemplate.executeTransaction(jdbc -> { jdbcTemplate.executeTransaction(jdbc -> {
jdbc.update("INSERT INTO base_table (id, created_by, create_time, status) VALUES (?, ?, ?, ?)", jdbc.update("INSERT INTO sys_account (id, username, created_by, create_time, account_status) VALUES (?, ?, ?, ?, ?)",
buildParams(id, 101, LocalDateTime.now(), 0)); buildParams(id, "testTransaction2", 101, LocalDateTime.now(), "55"));
}); });
Optional<Map<String, Object>> first = jdbcTemplate Optional<Map<String, Object>> first = jdbcTemplate
.queryFirst("SELECT * FROM base_table WHERE id = ?", buildParams(id)); .queryFirst("SELECT * FROM sys_account WHERE id = ?", buildParams(id));
log.info("first: {}", first); log.info("first: {}", first);
assertTrue(first.isPresent()); assertTrue(first.isPresent());
} }
@ -137,8 +181,8 @@ class SimpleJdbcTemplateTests {
long id = this.idGenerator.nextId(); long id = this.idGenerator.nextId();
try { try {
jdbcTemplate.commitIfTrue(jdbc -> { jdbcTemplate.commitIfTrue(jdbc -> {
jdbc.update("INSERT INTO base_table (id, created_by, create_time, status) VALUES (?, ?, ?, ?)", jdbc.update("INSERT INTO sys_account (id, username, created_by, create_time, account_status) VALUES (?, ?, ?, ?, ?)",
buildParams(id, 102, LocalDateTime.now(), 0)); buildParams(id, "testTransaction3", 102, LocalDateTime.now(), "55"));
throw new NullPointerException(); throw new NullPointerException();
}); });
} }
@ -146,7 +190,7 @@ class SimpleJdbcTemplateTests {
// ignore // ignore
} }
Optional<Map<String, Object>> first = jdbcTemplate Optional<Map<String, Object>> first = jdbcTemplate
.queryFirst("SELECT * FROM base_table WHERE id = ?", buildParams(id)); .queryFirst("SELECT * FROM sys_account WHERE id = ?", buildParams(id));
log.info("first: {}", first); log.info("first: {}", first);
assertTrue(!first.isPresent()); assertTrue(!first.isPresent());
} }
@ -155,13 +199,13 @@ class SimpleJdbcTemplateTests {
{ {
long id = this.idGenerator.nextId(); long id = this.idGenerator.nextId();
jdbcTemplate.commitIfTrue(jdbc -> { jdbcTemplate.commitIfTrue(jdbc -> {
jdbc.update("INSERT INTO base_table (id, created_by, create_time, status) VALUES (?, ?, ?, ?)", jdbc.update("INSERT INTO sys_account (id, username, created_by, create_time, account_status) VALUES (?, ?, ?, ?, ?)",
buildParams(id, 103, LocalDateTime.now(), 0)); buildParams(id, "testTransaction4", 103, LocalDateTime.now(), "55"));
return false; return false;
}); });
Optional<Map<String, Object>> first = jdbcTemplate Optional<Map<String, Object>> first = jdbcTemplate
.queryFirst("SELECT * FROM base_table WHERE id = ?", buildParams(id)); .queryFirst("SELECT * FROM sys_account WHERE id = ?", buildParams(id));
log.info("first: {}", first); log.info("first: {}", first);
assertTrue(!first.isPresent()); assertTrue(!first.isPresent());
} }
@ -170,72 +214,57 @@ class SimpleJdbcTemplateTests {
{ {
long id = this.idGenerator.nextId(); long id = this.idGenerator.nextId();
jdbcTemplate.commitIfTrue(jdbc -> { jdbcTemplate.commitIfTrue(jdbc -> {
jdbc.update("INSERT INTO base_table (id, created_by, create_time, status) VALUES (?, ?, ?, ?)", jdbc.update("INSERT INTO sys_account (id, username, created_by, create_time, account_status) VALUES (?, ?, ?, ?, ?)",
buildParams(id, 104, LocalDateTime.now(), 0)); buildParams(id, "testTransaction5", 104, LocalDateTime.now(), "55"));
return true; return true;
}); });
Optional<Map<String, Object>> first = jdbcTemplate Optional<Map<String, Object>> first = jdbcTemplate
.queryFirst("SELECT * FROM base_table WHERE id = ?", buildParams(id)); .queryFirst("SELECT * FROM sys_account WHERE id = ?", buildParams(id));
log.info("first: {}", first); log.info("first: {}", first);
assertTrue(first.isPresent()); assertTrue(first.isPresent());
} }
} }
@Test
void testBatch() throws Exception {
Random random = ThreadLocalRandom.current();
LocalDate handleDate = LocalDate.of(1949, 10, 1);
List<DbRecord> datas = Lists.newArrayList();
while (handleDate.isBefore(LocalDate.of(2008, 8, 8))) {
DbRecord r1 = new DbRecord();
r1.put("username", "张三2");
r1.put("usage_date", handleDate);
r1.put("usage_duration", random.nextInt(500));
datas.add(r1);
DbRecord r2 = new DbRecord();
r2.put("username", "李四2");
r2.put("usage_date", handleDate);
r2.put("usage_duration", random.nextInt(500));
datas.add(r2);
handleDate = handleDate.plusDays(1L);
}
try {
List<int[]> result = jdbcTemplate.batchUpdate(
"insert into test_table (username, usage_date, usage_duration) values (?,?,?)",
buildBatchParams(datas, item -> buildParams(
item.getValueAsString("username"),
item.getValueAsString("usage_date"),
item.getValueAsString("usage_duration"))),
400);
long sum = Numbers.sum(ArrayTools.concatIntArray(result));
assertEquals(datas.size(), sum);
log.info("sum: {}", sum);
}
catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test @Test
void testBean() throws Exception { void testBean() throws Exception {
Optional<TestBean> t = jdbcTemplate.queryFirst( Optional<AccountPO> t = jdbcTemplate.queryFirst(
"SELECT * FROM test_table WHERE id = ?", "SELECT * FROM sys_account WHERE id = ?",
buildParams(22915), buildParams(18L),
RowMapper.beanRowMapper(TestBean.class)); RowMapper.beanRowMapper(AccountPO.class));
log.info("t: {}", t); assertEquals(
new AccountPO(18L, "zhouxy18", "1",
LocalDateTime.of(2000, 1, 1, 0, 0), 118L,
LocalDateTime.of(2000, 1, 29, 0, 0), null, 7L),
t.get());
log.info("{}", t);
} }
} }
class TestBean { class AccountPO {
Long id; Long id;
String username; String username;
LocalDate usageDate; String accountStatus;
Long usageDuration; LocalDateTime createTime;
Long createdBy;
LocalDateTime updateTime;
Long updatedBy;
Long version;
public AccountPO() {
}
public AccountPO(Long id, String username, String accountStatus, LocalDateTime createTime, Long createdBy,
LocalDateTime updateTime, Long updatedBy, Long version) {
this.id = id;
this.username = username;
this.accountStatus = accountStatus;
this.createTime = createTime;
this.createdBy = createdBy;
this.updateTime = updateTime;
this.updatedBy = updatedBy;
this.version = version;
}
public Long getId() { public Long getId() {
return id; return id;
@ -253,25 +282,78 @@ class TestBean {
this.username = username; this.username = username;
} }
public LocalDate getUsageDate() { public String getAccountStatus() {
return usageDate; return accountStatus;
} }
public void setUsageDate(LocalDate usageDate) { public void setAccountStatus(String accountStatus) {
this.usageDate = usageDate; this.accountStatus = accountStatus;
} }
public Long getUsageDuration() { public LocalDateTime getCreateTime() {
return usageDuration; return createTime;
} }
public void setUsageDuration(Long usageDuration) { public void setCreateTime(LocalDateTime createTime) {
this.usageDuration = usageDuration; this.createTime = createTime;
}
public Long getCreatedBy() {
return createdBy;
}
public void setCreatedBy(Long createdBy) {
this.createdBy = createdBy;
}
public LocalDateTime getUpdateTime() {
return updateTime;
}
public void setUpdateTime(LocalDateTime updateTime) {
this.updateTime = updateTime;
}
public Long getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(Long updatedBy) {
this.updatedBy = updatedBy;
}
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
@Override
public int hashCode() {
return Objects.hash(id, username, accountStatus, createTime, createdBy, updateTime, updatedBy, version);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AccountPO other = (AccountPO) obj;
return Objects.equals(id, other.id) && Objects.equals(username, other.username)
&& Objects.equals(accountStatus, other.accountStatus) && Objects.equals(createTime, other.createTime)
&& Objects.equals(createdBy, other.createdBy) && Objects.equals(updateTime, other.updateTime)
&& Objects.equals(updatedBy, other.updatedBy) && Objects.equals(version, other.version);
} }
@Override @Override
public String toString() { public String toString() {
return "TestBean [id=" + id + ", username=" + username + ", usageDate=" + usageDate + ", usageDuration=" return "AccountPO [id=" + id + ", username=" + username + ", accountStatus=" + accountStatus + ", createTime="
+ usageDuration + "]"; + createTime + ", createdBy=" + createdBy + ", updateTime=" + updateTime + ", updatedBy=" + updatedBy
+ ", version=" + version + "]";
} }
} }