2012-05-18 5 views
5

Ein frustrierendes Problem mit Hibernate 3.6.9. MS SQL Server 2008. Beachten Sie die Ausnahme und die ungerade Spaltenindexreferenz.Hibernate-Ausnahme Nullwert wurde einer Eigenschaft des primitiven Typs Setter zugewiesen

Die HQL-Abfrage selbst:

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

Der Stack-Trace:

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 

Nun, würde ich dies von der Logik verstehen (und von googeln), wenn Folgendes nicht wahr wäre

a) Auf jede Instantiierung von DataStoreReference folgt kurz eine setUsage von System.currentTimeMillis) b) das Item ist im Mapping als not-null gekennzeichnet (siehe unten) c) Die exportierte Tabelle zeigt Nullen nur in der Spalte f_external. Die Verwendungsspalte hat vollkommen vernünftige lange Zahlen.

Die 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; 

durch generische unmodifizierten Getter/Setter gefolgt.

Die Zuordnungsdatei:

<?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> 
+0

Oh hier ist der eigentliche Code, der das Problem löst: \t \t \t Abfrage q = this.session.createQuery (Hib) \t \t \t .setString ("Hash", Hash); \t \t \t @SuppressWarnings ("ungeprüft") \t \t \t List Referenz = q.list(); // boom – MJB

+0

Hibernate holt dies in einem Join, also denke ich, dass der Index 14 ist, die Spalte ist wahrscheinlich im 'DataStoreContainer'. – dasblinkenlight

+0

logisch, aber die im Stapel erwähnte Spalte ist Verwendung, die nur in DataStoreReference ist. Ich habe die Frage aktualisiert, um die andere Zuordnungsdatei einzuschließen – MJB

Antwort

2

Es stellt sich heraus, es ist ein Fehler mit den erweiterten Hibernate 3.6 MS SQL-Dialekten. Wenn Sie SQLServer2005 oder SQLServer2008-Dialekte erweitern, wird dieses Problem auftreten. Die Verwendung des älteren SQLServer-Dialekts (der im Wesentlichen mit Hibernate 3.3x ausgeliefert wird) funktioniert nicht. Wahrscheinlich hat etwas mit der Paging-Unterstützung zu tun. Seufzer

22

Die Fehlermeldung ist klar: In zumindest einer Reihe der Spalten f_usage hat einen Nullwert. Dieser Nullwert kann nicht so lange in einen primitiven Typ eingegeben werden, da primitive Typen nicht null darstellen können.

Das Nicht-Null-Attribut in der Property-Klausel hat keine Auswirkungen, wenn bereits ein Nullwert in der Datenbank vorhanden ist. Das Nicht-Null-Attribut wird nur für die DMD-Generierung verwendet. Die Spalte f_usage Ihrer Datenbanktabelle t_dsref erlaubt jedoch wahrscheinlich Nullwerte (überprüfen Sie mit desc t_dsref in sql).

Lösung: Austausch lang mit Long:

private Long usage; 

und wenn der Wert Verwenden Sie den Nullzustand zu behandeln, zum Beispiel

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

(Sie verwenden Getter und Setter für den Zugang mit Hibernate, also sollte dieses Codelet nicht im Getter sein, weil in der Datenbank ein Nullwert nach einem Update weiterhin Null sein sollte, aber Sie können es in einem zweiten Getter, den Sie überall sonst verwenden, oder Feldzugriff für Hibernate .)

Meine allgemeine Empfehlung: Primitive Datentypen sollten nur für Hibernate-Eigenschaften verwendet werden, wenn die Spalte mit NOT NULL in der Datenbank markiert ist.

+1

Einverstanden. Als Best Practice bei der Verwendung von Hibernate sollten Sie keine primitiven Datentypen verwenden (ändern Sie Ihre 'long'- und' int'-Werte in 'Long' und' Integer'). –

+3

Dies ist bei Weitem keine Best Practice. Verwenden Sie ein Primitiv, wenn die Spalte nicht null ist. Verwenden Sie einen Wrapper, wenn es nullfähig ist. –

+1

good advice but --- Wie bereits erwähnt, hat die Mapping-Datei die Verwendung als nicht-null = wahr. Die Datenbank wurde von HIBERNaTE mithilfe der integrierten Schemadienstprogramme generiert. Auch die Daten wurden überprüft. In der Verwendungsspalte gibt es NO NULL-Werte. Die Datenbank wurde von Grund auf mit Hibernate erstellt und nur Hibernate hat sie ausgefüllt. – MJB

1

Hibernate benötigt einige Revisionen, um den realen Szenarien der Unternehmensentwicklung zu entsprechen. Die Verwendung von Objekten anstelle von Primitiven führt zu viel mehr Problemen als das, was in diesem Zusammenhang gelöst wird.

Ich habe Java EE Enterprise-Anwendungen seit 2002 programmiert. Die beste Lösung für diesen Anwendungsfall, unter Berücksichtigung, dass Sie wahrscheinlich viele Tabellen haben, die Codetabellen mit Nullwerten referenzieren, besteht darin, die Datenbank nach Möglichkeit zu aktualisieren.

Wenn Sie beispielsweise eine Personentabelle mit einem Verweis auf eine Generierungscodetabelle für Titel wie Junior, Senior usw. haben und viele Einträge null sind, aktualisieren Sie die Codetabelle, um eine unbekannte Referenz zu erhalten, und aktualisieren Sie dann die Tabellendaten für alle Nullen, die auf diese Referenz verweisen. Da die meisten Java EE-Anwendungen groß und schlecht codiert sind, können Sie versuchen, die Einstiegspunkte für diese Tabellen zu aktualisieren, aber höchstwahrscheinlich ist es ein Chaos und es können alle möglichen Einstiegspunkte von Cron-Jobs, Web-Services usw. ausgeführt werden DB diese Nullen zu fangen und sie auf den unbekannten Eintrag zu setzen und sich selbst Kopfschmerzen zu ersparen. Wenn Ihr Gebäude von Grund auf neu ist, ist es auch ein Chaos mit dem Winterschlaf, da es nicht einfach ist, einen Setter mit einem Primitiv aufzurufen, und es ist null, machen Sie einfach 0 oder -1, aber dann wieder I habe weniger als 20 Stunden Winterschlaf. Ich lese gerade die Benutzertypen auf, also muss ich etwas mehr lesen und sehen, wie sie funktionieren.

Objekte in großen Java EE-Anwendungen sind ein Albtraum zur Laufzeit mit der Qualität von Codern auf dem heutigen Markt.

1

Solche Fehler treten in Hibernate auf, wenn Sie für einige Spalten primitive Typen verwenden, diese Felder jedoch in der Datenbank null sind. Lösungen:

Lösung Eins: Wrapper-Klassen verwenden (Integer for int ...) Lösung Zwei: Definieren Sie Standardwerte für Spalten.

Verwandte Themen