如何创建一个 TypeConverter 将 LocalDate 转换为 Room 可以理解/保存的格式?

如何解决如何创建一个 TypeConverter 将 LocalDate 转换为 Room 可以理解/保存的格式?

我正在使用 Room。我需要关于如何将 LocalDatejava.time 转换为格式的指导(可能是 LongTimeStampsql.Date 或者我什至不知道还有什么)这样我就可以将日期保存到数据库中。

我有一个图书实体:

@Entity
data class Book(
    @ColumnInfo(name = "date") val date: LocalDate,@ColumnInfo(name = "count") val count: Int,@PrimaryKey(autoGenerate = true)
    val id: Int? = null
)

我还创建了 Book DAO:

@Dao
interface BookDao {
    @Query("SELECT * FROM book WHERE :date >= book.date")
    fun getBooks(date: LocalDate): List<Book>
}

现在,我不确定如何创建将 LocalDate 转换为 . . . (同样,我什至不知道我应该将 LocalDate 转换成什么。是 LongTimeStampsql.Date 还是其他任何东西)。

认为我应该将 LocalDate 转换为 sql.Date 以便 Room 可以保存它。所以,我像这样创建了我的转换器:

Converters.kt

class Converters {
    @TypeConverter
    fun convertLocalDateToSqlDate(localDate: LocalDate?): Date? {
        return localDate?.let { Date.valueOf(localDate.toString()) }
    }

    @TypeConverter
    fun convertSqlDateToLocalDate(sqlDate: Date?): LocalDate? {
        val defaultZoneId = systemDefault()
        val instant = sqlDate?.toInstant()
        return instant?.atZone(defaultZoneId)?.toLocalDate()
    }
}

但是,我收到错误:

error: Cannot figure out how to save this field into database. You can consider adding a type converter for it.
    private final java.time.LocalDate date = null;

解决方法

您遇到的问题是 TypeConverter 应该转换为 Room 支持插入/提取数据的一组特定类型。

比较常见的有 Int、Long Byte、Byte[]、Float、Double、Decimal、String、BigInt、BigDecimal。

  • 可能还有其他类型,但可以使用的类型有限

所以消息是说请转换您的 LocalDate 或 Date,因为它无法处理它们。

我建议将日期存储为 unix 日期(除非您想要以毫秒为单位存储时间的微秒精度(这在 sqlite 中使用日期/时间函数时可能有点尴尬,并且可能需要强制转换))即作为多头或整数。

这样做你:

  • 将最小化用于存储值的存储量,
  • 将能够利用SQLite Date and Time functions
  • 可以轻松地将它们提取为非常灵活的格式,
  • 您可以按原样提取它们,然后使用类函数对它们进行格式转换,
  • 您将不需要 TypeConverters 用于上述操作。

这是一个显示一些功能的示例,将它们存储为 unix 时间戳

首先使用默认日期的 Book 实体版本:-

@Entity
data class Book(
    @ColumnInfo(name = "date",defaultValue = "(strftime('%s','now','localtime'))")
    val date: Long? = null,@ColumnInfo(name = "count")
    val count: Int,@PrimaryKey(autoGenerate = true)
    val id: Int? = null
)
  • 请参阅 SQLITE 日期和时间函数以了解上述内容。总之,上面允许您插入一行并将日期和时间设置为当前日期时间
  • 请参阅 insertBook 函数以仅使用提供的计数进行插入。

陪书实体书道:-

@Dao
interface BookDao {
    @Insert /* insert via a book object */
    fun insert(book: Book): Long
    @Query("INSERT INTO BOOK (count) VALUES(:count)")

    /* insert supplying just the count id and date will be generated */
    fun insertBook(count: Long): Long
    @Query("SELECT * FROM book")

    /* get all the books  as they are stored into a list of book objects*/
    fun getAllFromBook(): List<Book>

    /* get the dates as a list of dates in yyyy-mm-dd format using the SQLite date function */
    @Query("SELECT date(date,'unixepoch','localtime') AS mydateAsDate FROM book")
    fun getDatesFromBook(): List<String>

    /* get the date + 7 days */
    @Query("SELECT date(date,'localtime','+7 days') FROM book")
    fun getDatesFromBook1WeekLater(): List<String>
}
  • 查看评论(以及活动和结果)

活动(非常标准的 BookDatabase 类,因此不包括在内)

class MainActivity : AppCompatActivity() {
    lateinit var db: BookDatabase
    lateinit var dao: BookDao
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        db = BookDatabase.getInstance(this)
        dao = db.getBookDao()

        /* Insert two rows */
        dao.insert(Book(System.currentTimeMillis() / 1000,10)) /* don't want millisecs */
        dao.insertBook(20) /* use the date columns default value (similar to the above) */

        /* get and log the date objects */
        for(b: Book in dao.getAllFromBook()) {
            Log.d("BOOKINFO_BOOK"," Date = ${b.date} Count = ${b.count} ID = ${b.id}")
        }

        /* get the dates in yyy-mm-dd format */
        for(s: String in dao.getDatesFromBook()) {
            Log.d("BOOKINFO_DATE",s)
        }

        /* get the dates but with a week added on */
        for(s: String in dao.getDatesFromBook1WeekLater()) {
            Log.d("BOOKINFO_1WEEKLATER",s)
        }
    }
}

运行后的日志:-

2021-04-16 14:28:50.225 D/BOOKINFO_BOOK:  Date = 1618547330 Count = 10 ID = 1
2021-04-16 14:28:50.225 D/BOOKINFO_BOOK:  Date = 1618583330 Count = 20 ID = 2
2021-04-16 14:28:50.226 D/BOOKINFO_DATE: 2021-04-16
2021-04-16 14:28:50.227 D/BOOKINFO_DATE: 2021-04-17
2021-04-16 14:28:50.228 D/BOOKINFO_1WEEKLATER: 2021-04-23
2021-04-16 14:28:50.228 D/BOOKINFO_1WEEKLATER: 2021-04-24
  • (注意对本地时间的调整(虽然用错了所以跳了))
  • 存储在 Book 对象和数据库中的前 2 行数据
  • 接下来的 2 行是由 SQLite 日期/时间函数转换为 YYYY-MM-DD 格式的日期
  • 将存储日期转换为 YYYY-MM-DD 后一周的日期的最后 2 行

根据数据库检查员的数据库:-

enter image description here

,

如果你想使用转换器,你可以按照文档的方式。在您的示例中,您尝试转换为 SQLdate,但 Android 建议使用 Long。

class Converters {
  @TypeConverter
  fun fromTimestamp(value: Long?): Date? {
    return value?.let { Date(it) }
  }

  @TypeConverter
  fun dateToTimestamp(date: Date?): Long? {
    return date?.time?.toLong()
  }
}

然后将@TypeConverters 注解添加到 AppDatabase。

LocalDate 应该是这样的:

class Converters {
    @TypeConverter
    fun fromTimestamp(value: Long?): LocalDate? {
        return value?.let { LocalDate.ofEpochDay(it) }
    }

    @TypeConverter
    fun dateToTimestamp(date: LocalDate?): Long? {
        val zoneId: ZoneId = ZoneId.systemDefault()
        return date?.atStartOfDay(zoneId)?.toEpochSecond()
    }
}

source

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-