问题描述
我在 MysqL 的表中有一个字段,它的类型为 DATETIME。 我将通过 jdbi 简单地阅读和使用它。
所以在MysqL中:
> desc user;
....
birth_date datetime
.....
在应用层,我尝试了如下非常不同的场景:
@sqlQuery("select birth_date from user where user_id = :userId")
java.sql.Date fetchDateOfBirthForUser(@Bind("userId")final Long userId);
或
@sqlQuery("select birth_date from user where user_id = :userId")
java.util.Date fetchDateOfBirthForUser(@Bind("userId")final Long userId);
或
@sqlQuery("select birth_date from user where user_id = :userId")
java.sql.Timestamp fetchDateOfBirthForUser(@Bind("userId")final Long userId);
甚至
@sqlQuery("select birth_date from user where user_id = :userId")
Long fetchDateOfBirthForUser(@Bind("userId")final Long userId);
更新 1: 我收到以下错误,而不是空值!
org.jdbi.v3.core.mapper.NoSuchMapperException: No mapper registered for type java.util.Date
这是我使用 java.util.Date
的时候。如果我使用我提到的任何其他类型,我会收到同样的错误:No mapper registered for type X
这是为什么?
更新 2:
使用映射器(时间戳和 java.sql.Date)给我 NullPointerException
。
数据库中的值,正如我之前提到的,是 DATETIME
。
@sqlQuery("select birth_date from user where user_id = :userId")
@UseRowMapper(DateMatter.class)
java.sql.Date fetchDateOfBirthForUser(@Bind("userId")final Long userId);
还有 DateMapper 类:
public class DateMatter implements RowMapper<Date> {
@Override
public Date map(ResultSet rs,StatementContext ctx) throws sqlException {
return rs.getDate("birth");
}
}
我使用了 rs.getDate()
、rs.getLong()
和 rs.getTimestamp()
方法。都导致 NPE。
现在,当我调用方法 dao.fetchDateOfBirthForUser(<user_id>);
时,我得到 NullPointerException
最后更新 解决方案出乎意料。我从应用程序指向另一个数据库,并查询另一个数据库进行验证!
解决方法
我可以确认,一切都应该按预期工作,请参阅下面的代码,它可以正常工作。 最好自己查一下数据库里面的数据,有可能是这个问题。
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.core.mapper.RowMapper;
import org.jdbi.v3.core.statement.StatementContext;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;
import org.jdbi.v3.sqlobject.config.RegisterRowMapper;
import org.jdbi.v3.sqlobject.customizer.Bind;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlScript;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
@Testcontainers
class DatetimeMysqlTest {
@Container
private static final MySQLContainer mysql = new MySQLContainer<>();
interface Dao {
@SqlScript("CREATE TABLE user (user_id integer,birth_date datetime)")
void create();
@SqlUpdate("INSERT INTO user (user_id,birth_date) VALUES (:userId,now())")
void insert(@Bind("userId") int userId);
@SqlQuery("SELECT birth_date from user WHERE user_id = :userId")
java.sql.Timestamp sqlTimestamp(@Bind("userId") int userId);
@SqlQuery("SELECT birth_date from user WHERE user_id = :userId")
java.time.LocalDateTime timeLocalDate(@Bind("userId") int userId);
@RegisterRowMapper(DateMatter.class)
@SqlQuery("SELECT birth_date from user WHERE user_id = :userId")
java.util.Date utilDate(@Bind("userId") int userId);
class DateMatter implements RowMapper<Date> {
@Override
public java.util.Date map(ResultSet rs,StatementContext ctx) throws SQLException {
return rs.getDate("birth_date");
}
}
}
@Test
void testDatetime() {
var jdbcUrl = mysql.getJdbcUrl();
var dao = Jdbi.create(jdbcUrl,mysql.getUsername(),mysql.getPassword())
.installPlugin(new SqlObjectPlugin())
.onDemand(Dao.class);
dao.create();
dao.insert(42);
System.out.println(dao.sqlTimestamp(42));
System.out.println(dao.timeLocalDate(42));
System.out.println(dao.utilDate(42));
}
}
输出:
2021-02-25 12:34:05.0
2021-02-25T12:34:05
2021-02-25
项目依赖
<dependencies>
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-core</artifactId>
<version>3.8.2</version>
</dependency>
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-sqlobject</artifactId>
<version>3.8.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
<version>5.7.0</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<scope>test</scope>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.14.3</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mysql</artifactId>
<version>1.14.3</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>