75 sqlite 里面的 boolean 的 ‘t‘ 和 ‘true‘ 和 1
Posted 蓝风9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了75 sqlite 里面的 boolean 的 ‘t‘ 和 ‘true‘ 和 1相关的知识,希望对你有一定的参考价值。
前言
呵呵 最近有一些 使用 sqlite 的场景
然后在使用 sqlite 的过程中, 我发现了一个问题 我的一个 boolean 的字段, 设置的值为 't', 但是通过 jpa 查询出来的实体该字段对应的值为 false, 呵呵 这里就是主要是围绕这个问题来展开
这里也可以看到一些 和 sqlite规范 相关的东西
环境如下 : jdk8 + org.xerial.sqlite-jdbc-3.31.1 + spring-boot-starter-data-jpa-2.3.4.RELEASE + hibernate-core-5.4.21.Final
现象
首先看一下 我这里数据库里面的一些状态信息
admin 这个 账户, enabled 为 true
但是当我通过页面去登录的时候, 登录接口响应如下, 呵呵 用户已禁用?, 这个禁用判断是通过 enabled 的标记来判断的
然后我们来看一下 查询出来的这个用户的信息, 呵呵 发现 user 的 enabled 果然为 false, 那么 这是为什么呢
调试
要描述这个问题 也还是比较简单, 所以这里就直接 长驱直入了
但是 要找到这块的代码, 还是 需要一些时间的, 当然 第一次碰到了, 可以记录下来, 后面方便查询
我们来到 获取 enabled 的这个字段的信息的地方, hydrate:3088, AbstractEntityPersister 这里是循环每一个字段的信息, 然后从 resultSet 中获取这个字段的相关信息, 然后设置到 实体里面
我们这里截取的主要是针对 enabled 的这个字段, admin 对应的记录的这个字段为 't' 或者 'true', 但是在 sqlite 里面 getInt 返回的是 0
假设我们吧 enabled 的这个字段修改成为 1, admin 对应的记录的 enabled 就会处理为 true 了
因为我们在 mysql 或者 postgresql 里面经常 boolean 字段一般可以设置为 1 或者 't' 或者 'true' 这几个都是等价的, 但是在 sqlite 里面就不一样了, 这个需要注意一下
再下面的 “public native synchronized int column_int(long stmt, int col)" 是本地方法, 我们就追不下去了, 不过可以大致的得出一个结论就是 如果是 数字 1, driver 会识别为 true, 其他的会识别为 false
假设我们吧 enabled 的这个字段修改成为 1 的情况
假设我们吧 enabled 的这个字段修改成为 true 的情况
上面的调用堆栈信息如下
getBoolean:212, JDBC3ResultSet (org.sqlite.jdbc3)
getBoolean:219, JDBC3ResultSet (org.sqlite.jdbc3)
getBoolean:-1, HikariProxyResultSet (com.zaxxer.hikari.pool)
doExtract:59, BooleanTypeDescriptor$2 (org.hibernate.type.descriptor.sql)
extract:47, BasicExtractor (org.hibernate.type.descriptor.sql)
nullSafeGet:257, AbstractStandardBasicType (org.hibernate.type)
nullSafeGet:253, AbstractStandardBasicType (org.hibernate.type)
nullSafeGet:243, AbstractStandardBasicType (org.hibernate.type)
hydrate:329, AbstractStandardBasicType (org.hibernate.type)
hydrate:3088, AbstractEntityPersister (org.hibernate.persister.entity)
loadFromResultSet:1907, Loader (org.hibernate.loader)
hydrateEntityState:1835, Loader (org.hibernate.loader)
instanceNotYetLoaded:1808, Loader (org.hibernate.loader)
getRow:1660, Loader (org.hibernate.loader)
getRowFromResultSet:745, Loader (org.hibernate.loader)
getRowsFromResultSet:1044, Loader (org.hibernate.loader)
processResultSet:995, Loader (org.hibernate.loader)
doQuery:964, Loader (org.hibernate.loader)
doQueryAndInitializeNonLazyCollections:350, Loader (org.hibernate.loader)
doList:2887, Loader (org.hibernate.loader)
doList:2869, Loader (org.hibernate.loader)
listIgnoreQueryCache:2701, Loader (org.hibernate.loader)
list:2696, Loader (org.hibernate.loader)
list:506, QueryLoader (org.hibernate.loader.hql)
list:400, QueryTranslatorImpl (org.hibernate.hql.internal.ast)
performList:219, HQLQueryPlan (org.hibernate.engine.query.spi)
list:1415, SessionImpl (org.hibernate.internal)
doList:1565, AbstractProducedQuery (org.hibernate.query.internal)
list:1533, AbstractProducedQuery (org.hibernate.query.internal)
getSingleResult:1581, AbstractProducedQuery (org.hibernate.query.internal)
getSingleResult:111, CriteriaQueryTypeQueryAdapter (org.hibernate.query.criteria.internal.compile)
doExecute:196, JpaQueryExecution$SingleEntityExecution (org.springframework.data.jpa.repository.query)
execute:88, JpaQueryExecution (org.springframework.data.jpa.repository.query)
doExecute:154, AbstractJpaQuery (org.springframework.data.jpa.repository.query)
execute:142, AbstractJpaQuery (org.springframework.data.jpa.repository.query)
invoke:195, QueryExecutorMethodInterceptor$QueryMethodInvoker (org.springframework.data.repository.core.support)
doInvoke:152, QueryExecutorMethodInterceptor (org.springframework.data.repository.core.support)
invoke:130, QueryExecutorMethodInterceptor (org.springframework.data.repository.core.support)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:80, DefaultMethodInvokingMethodInterceptor (org.springframework.data.projection)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceedWithInvocation:-1, 522366107 (org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda$1814)
invokeWithinTransaction:367, TransactionAspectSupport (org.springframework.transaction.interceptor)
invoke:118, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:139, PersistenceExceptionTranslationInterceptor (org.springframework.dao.support)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:149, CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor (org.springframework.data.jpa.repository.support)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:95, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:212, JdkDynamicAopProxy (org.springframework.aop.framework)
findByUsername:-1, $Proxy169 (com.sun.proxy)
signIn:87, UserService
// 省略若干堆栈信息
doInvoke:190, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:105, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:878, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:792, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1040, DispatcherServlet (org.springframework.web.servlet)
doService:943, DispatcherServlet (org.springframework.web.servlet)
processRequest:1006, FrameworkServlet (org.springframework.web.servlet)
doGet:898, FrameworkServlet (org.springframework.web.servlet)
service:626, HttpServlet (javax.servlet.http)
service:883, FrameworkServlet (org.springframework.web.servlet)
service:733, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:100, RequestContextFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, FormContentFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:201, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:202, StandardWrapperValve (org.apache.catalina.core)
invoke:97, StandardContextValve (org.apache.catalina.core)
invoke:541, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:143, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:374, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:868, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1590, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)
2.1. Boolean Datatype
如下内容来自于 Datatypes In SQLite
看文档上面说的是 存储为 0 或者 1, 但是 实际上我们放的是 't' 或者是 'true' 也能够查询出来, 所以 应该是放的完整的值, 取对应的数据的时候再做的 cast
参考
以上是关于75 sqlite 里面的 boolean 的 ‘t‘ 和 ‘true‘ 和 1的主要内容,如果未能解决你的问题,请参考以下文章
Android中SQLite的Cursor如何取得boolean型数据
Can't migrate a table to Room do to an error with the way booleans is saved in Sqlite