Hibernate 3.6.9でイライラする問題が発生しています。 MS SQL Server2008。例外と奇数列のインデックス参照に注意してください。
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:
DataStoreReference
private long id;
private String hash;
private long date;
private long sze;
private long usage;
private int state;
private String external;
private DataStoreContainer container;
続いて、一般的な未変更のゲッター/セッター。
マッピングファイル:
<?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>
これは、拡張されたHibernate 3.6 MS SQL方言のバグであることが判明しました。 SQLServer2005またはSQLServer2008方言を拡張すると、この問題が発生します。古いSQLServer方言(Hibernate 3.3xに同梱されているもののほとんど)を使用していません。おそらく、ページングのサポートに関係するものが導入されました。はぁ
エラーメッセージは明らかです。少なくとも1つの行で、列f_usageにnull値があります。プリミティブ型はnullを表すことができないため、このnull値をlongのようなプリミティブ型に入れることはできません。
データベースにすでにnull値がある場合、property句のnot-null属性は無効です。 not-null属性のみがdmd生成に使用されます。しかし、データベーステーブルt_dsrefのf_usage列は、おそらくnull値を許可します(desc t_dsref
in sql)。
解決策:LongとLongの交換:
private Long usage;
値を使用するときは、null条件を処理する必要があります。たとえば、
if (usage != null) {
return usage.longValue();
else
return -1;
(hibernateでのアクセスにゲッターとセッターを使用しているため、データベースではnull値は更新後も引き続きnullである必要があるため、このコードレットをgetterに含めることはできませんが、使用する2番目のgetterで実行できます他のすべての場所、または休止状態のフィールドアクセスを実行します。)
私の一般的な推奨事項:プリミティブデータ型は、列がNOT NULLでマークされている場合にのみ休止状態のプロパティに使用する必要がありますデータベース内。
このようなエラーは、一部の列にプリミティブ型を使用しているが、フィールドがDBでnullの場合にHibernateで発生します。ソリューション:
解決策1:Wrapperクラスを使用する(整数は整数...)解決策2:列のデフォルト値を定義する。
Hibernateは、エンタープライズ開発の実際のシナリオに一致するようにいくつかの修正を必要とします。プリミティブの代わりにオブジェクトを使用すると、このコンテキストで解決される問題よりも多くの問題が発生します。
私は2002年以来、Java EEエンタープライズアプリをコーディングしています。null値のコードテーブルを参照する多くのテーブルがあることを考慮して、このユースケースの最良の解決策は、データベースを更新することです。可能。
たとえば、ジュニア、シニアなどのタイトルを示す世代コードテーブルへの参照を含むPersonsテーブルがあり、多くのエントリがnullの場合、不明な参照を含むようにコードテーブルを更新し、すべてのテーブルデータを更新します。その参照を指すにはnull。大部分のJava EEアプリはサイズが大きく、正しくコーディングされていないので、これらのテーブルへのエントリポイントを更新してみることができますが、ほとんどの場合、混乱し、あらゆる種類のエントリポイントがcronから実行される可能性があります。ジョブ、Webサービスなどなので、DBを更新してこれらのnullをキャッチし、デフォルトで不明なエントリにして、頭痛を軽減します。建物を最初から作成する場合、これは休止状態の混乱でもあります。 hibernateがプリミティブを使用してセッターを呼び出そうとしていることを伝えるには、nullにするだけで0または-1にしますが、ここでも20時間未満のhibernateエクスペリエンスしかありません。ユーザータイプを読み取るだけなので、もう少し読んで、それらがどのように機能するかを確認してください。
大規模なオブジェクトJava= EEアプリは、現在市場に出回っているコーダーの品質を備えた実行時の悪夢です。