JDBI -> 将 MySql DATETIME 读入 java.sql.Date 或类似的
JDBI -> Reading MySql DATETIME into the java.sql.Date or similiar
我在 MySQL 的 table 中有一个 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 class:
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>
我在 MySQL 的 table 中有一个 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 class:
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>