【问题标题】:Hibernate native SQL query type mapping from java.sql.Date to java.time.LocalDate从 java.sql.Date 到 java.time.LocalDate 的 Hibernate 本机 SQL 查询类型映射
【发布时间】:2019-04-09 12:43:12
【问题描述】:

我正在使用 Hibernate 本机查询进行 SELECT 查询,如下所示:

public List<SomeDTO> findDTOs() {
    StringBuilder sql = new StringBuilder();
    sql.append(" SELECT id as id, localDateColumn as date, ");

    sql.append(" FROM t");
    Query query = entityManager.createNativeQuery(sql.toString());
    query.unwrap(SQLQuery.class)
        .addScalar("id", StandardBasicTypes.LONG)
        .addScalar("localDateColumn", DateType.INSTANCE)
        .setResultTransformer(Transformers.aliasToBean(SomeDTO.class));
    return query.getResultList();
  }

我尝试使用StandardBasicTypes.DATE 或DateType.INSTANCE,但不起作用。我知道映射java.sql.Types#DATE 和java.util.Date 效果很好。

我想知道如何将java.sql.Types#DATE 映射到java.time.LocalDate。

【问题讨论】:

    标签: mysql hibernate spring-boot jpa


    【解决方案1】:

    因为我没有使用Entity 作为返回数据类型。 AttributeConverter 在这种情况下没有用。 我通过在字段的设置器中手动将java.util.Date 转换为java.time.LocalDate 解决了这个问题。

    Setter 将如下所示:

    public void setLocalDateColumn(java.util.Date value){
        // convert into LocalDate
        // set
    }
    

    如果您在转换时收到UnsupportedOperationException。你可能仍然会在java.util.Date 中得到java.sql.Date。这样做: Instant.ofEpochMilli(value.getTime()).atZone(DefaultZoneId).toLocalDate();

    【讨论】:

      【解决方案2】:

      你的方法有很多问题。

      风险 SQL 注入攻击

      您使用字符串连接构建 SQL 的方式非常危险,可能会将您的应用程序暴露给SQL injection attacks。

      StringBuilder sql = new StringBuilder();
      sql.append(" SELECT id as id, localDateColumn as date, ");
      
      sql.append(" FROM t");
      Query query = entityManager.createNativeQuery(sql.toString());
      

      此外,它甚至不正确,因为您在 FROM 子句之前附加了 ,。如果要动态构建查询,则需要使用 Criteria API。

      别名使用不当

      您将localDateColumn 列设置为date 别名,如下所示:

      sql.append(" SELECT id as id, localDateColumn as date, ");
      

      但是当你使用addScalar设置休眠类型时,你使用localDateColumn:

      .addScalar("localDateColumn", DateType.INSTANCE)
      

      现在,根据您的问题标题,如果 localDateColumn 是 MySQL DATE 列类型,并且您想将其映射到 LocalDate Java 对象,您应该这样做:

      .addScalar("date", LocalDateType.INSTANCE)
      

      【讨论】:

      • 我只是使用虚拟 SQL 来简单解释方法,请忽略语法或别名,问题是关于映射日期类型。建议的解决方案返回java.util.Date,但我希望它转换为java.time.LocalDate。请看我的回答。
      • 如果你使用.addScalar("date", LocalDateType.INSTANCE),你应该得到它。
      • 您绝对应该仔细阅读我的回答,因为您的代码中存在比您最初发布问题的问题更大的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-02
      • 1970-01-01
      • 2014-10-15
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多