12

Hibernate 3.6.9 有一个令人沮丧的问题。MS SQL Server 2008。注意异常和奇数列索引参考。

HQL 查询本身:

Select r from DataStoreReference r join fetch r.container c where r.hash=:hash and r.state=0

堆栈跟踪:

2012-05-16 00:01:22,184 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT.  
2012-05-16 00:01:22,186 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT.  
2012-05-16 00:01:22,188 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - Invalid column index 14.  
2012-05-16 00:01:22,190 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT.  
2012-05-16 00:01:22,193 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - The value supplied cannot be converted to BIGINT.  
2012-05-16 00:01:22,194 [BackgroundDeletionThread] ERROR org.hibernate.util.JDBCExceptionReporter - Invalid column index 14.  
2012-05-16 00:01:22,194 [BackgroundDeletionThread] ERROR com.flipper.utils.ServerErrorHandlerStrategy - reportError: Db :: com.flipper.datastore.workers.BackgroundDeletionThread.executeWork:87 :: EXCEPTION : com.flipper.datastore.exceptions.DBStoreException: Null value was assigned to a property of primitive type setter of com.flipper.datastore.model.DataStoreReference.usage com.flipper.datastore.exceptions.DBStoreException: Null value was assigned to a property of primitive type setter of com.flipper.datastore.model.DataStoreReference.usage  
    at com.flipper.datastore.impl.hib.HibernateDBStore.getAllReferences(HibernateDBStore.java:301)
    at    com.flipper.datastore.workers.BackgroundDeletionThread.processEntry(BackgroundDeletionThread.java:165)
    at com.flipper.datastore.workers.BackgroundDeletionThread.processSet(BackgroundDeletionThread.java:138)
    at com.flipper.datastore.workers.BackgroundDeletionThread.executeWork(BackgroundDeletionThread.java:84)
    at com.flipper.datastore.workers.BackgroundDeletionThread.run(BackgroundDeletionThread.java:60)
Caused by: org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter of com.flipper.datastore.model.DataStoreReference.usage
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:109)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:583)
    at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:229)
    at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3847)
    at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:152)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
    at org.hibernate.loader.Loader.doQuery(Loader.java:857)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
    at org.hibernate.loader.Loader.doList(Loader.java:2542)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
    at org.hibernate.loader.Loader.list(Loader.java:2271)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:459)
    at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:365)
    at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
    at com.flipper.message.dao.DataStoreDao.getAllReferencesByHash(DataStoreDao.java:136)
    at com.flipper.datastore.impl.hib.HibernateDBStore.getAllReferences(HibernateDBStore.java:298)
    ... 4 more
Caused by: java.lang.IllegalArgumentException
    at sun.reflect.GeneratedMethodAccessor556.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
    ... 21 more

现在,如果以下不正确,我会从逻辑(和谷歌搜索)中理解这一点

a) DataStoreReference 的每个实例化后紧跟 System.currentTimeMillis 的 setUsage) b) 该项目在映射中被标记为非空(见下文) c) 导出的表仅在 f_external 列中显示空值。使用列具有完全合理的长数字。

POJO:

数据存储参考

private long id;


private String hash;    
private long date;  
private long sze;   
private long usage; 

private int state;  
private String external;
private DataStoreContainer container; 

其次是通用的未修改的getter/setter。

映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.flippr.datastore.model">
  <class name="DataStoreReference" table="t_dsref">
    <id name="id">
      <column name="ds_reference_id"/>
      <generator class="native"/>
    </id>
    <property name="hash" not-null="true" column="f_hash" lazy="false" index="idx_hash_dsr" type="string" length="128" />
    <property name="state" not-null="true" column="f_state" lazy="false" index="idx_hash_dsr,idx_size_dsr,idx_usage_dsr" type="integer"/>
    <!--  hibernate hates the name size -->
    <property name="sze" not-null="true" column="f_size" lazy="false" index="idx_size_dsr" type="long"/>
    <property name="date" not-null="true" column="f_date" lazy="false" type="long"/>    
    <property name="usage" not-null="true" column="f_usage" lazy="false" index="idx_usage_dsr" type="long"/>
    <property name="external" not-null="false" column="f_ext" lazy="false" type="string" length="160" />

    <many-to-one name="container" class="com.flipper.datastore.model.DataStoreContainer" 
     column="entity_id" foreign-key="fk_ds_container_id_dsr"  not-found="ignore" not-null="true"/>
   </class>
</hibernate-mapping>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.flipper.datastore.model">
  <class name="DataStoreContainer" table="t_dscnt">
    <id name="id">
      <column name="ds_container_id"/>
      <generator class="native"/>
    </id>
    <property name="containerType" column="f_type" index="idx_containerType_dsc" lazy="false" type="integer"/>
    <property name="fileCount" column="f_fc" lazy="false" type="long"/>
    <property name="deletedCount" column="f_dc" lazy="false" type="long"/>
    <property name="path" column="f_path" length="255" lazy="false"  type="string"/>
    <set cascade="save-update,delete,delete-orphan,all-delete-orphan" inverse="true" name="documents">
      <key column="entity_id" />
      <one-to-many class="com.flipper.datastore.model.DataStoreReference"/>
    </set>
  </class>
</hibernate-mapping>
4

4 回答 4

33

错误消息很清楚:在至少一行中,列 f_usage 具有空值。这个 null 值不能放入像 long 这样的原始类型中,因为原始类型不能表示 null。

当数据库中已经存在空值时,property 子句中的非空属性无效。not-null 属性仅用于 dmd 生成。但是数据库表 t_dsref 的 f_usage 列可能允许空值(desc t_dsref在 sql 中检查)。

解决方案:用Long交换long:

private Long usage; 

并且在使用该值时,您必须处理 null 条件,例如

if (usage != null) {
  return usage.longValue();
else
  return -1;

(您正在使用 getter 和 setter 来访问 hibernate,所以这个 codelet 不应该在 getter 中,因为在数据库中,更新后 null 值应该继续为 null,但您可以在您使用的第二个 getter 中执行此操作在其他任何地方,或者您为休眠进行字段访问。)

我的一般建议:如果列在数据库中标记为 NOT NULL,则原始数据类型应仅用于休眠属性。

于 2012-05-18T07:09:16.543 回答
5

当您对某些列使用原始类型但该字段在 DB 中为空时,此类错误会在 Hibernate 中发生。解决方案:

解决方案一:使用 Wrapper 类(Integer for int ...) 解决方案二:定义列的默认值。

于 2017-01-16T08:29:56.427 回答
3

原来这是增强的 Hibernate 3.6 MS SQL 方言的错误。如果您扩展 SQLServer2005 或 SQLServer2008 方言,您将遇到此问题。使用较旧的 SQLServer 方言(这几乎是 Hibernate 3.3x 附带的)你不需要。可能与引入的分页支持有关。叹

于 2012-06-19T02:12:44.067 回答
1

Hibernate 需要一些修改以匹配企业开发的现实生活场景。使用对象而不是原语会导致比在此上下文中解决的问题更多的问题。

自 2002 年以来,我一直在编写 Java EE 企业应用程序。考虑到您可能有许多引用具有空值的代码表的表,最好的解决方案是尽可能更新数据库。

例如,如果您有一个引用生成代码表的人员表来表示初级、高级等头衔,并且许多条目为空,请更新代码表以具有未知引用,然后更新所有的表数据空值指向该引用。作为大多数大型且编码错误的 Java EE 应用程序,您可以尝试更新这些表的入口点,但很可能这是一团糟,并且可能有各种入口点从 cron 作业、Web 服务等运行,因此请更新DB 来捕获这些空值并将它们默认为未知条目,让您自己头疼。如果您从头开始构建,那么这也是休眠的一团糟,因为从我可以告诉休眠的内容来看,这并不是很容易告诉您尝试使用原语调用设置器,并且它' s null 只需将其设为 0 或 -1,但我的休眠体验也不足 20 小时。我刚刚阅读了用户类型,所以我必须阅读更多内容并了解它们是如何工作的。

大型 Java EE 应用程序中的对象在运行时是一场噩梦,与当今市场上的编码器质量一样。

于 2015-12-07T04:58:28.837 回答