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>