2012-05-18 7 views
5

Tiene un problema frustrante con Hibernate 3.6.9. MS SQL Server 2008. Observe la excepción y la referencia de índice de columna impar.excepción de hibernación El valor nulo se asignó a una propiedad del configurador de tipo primitivo

El HQL misma consulta:

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

El seguimiento de pila:

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 

Ahora, lo entendería esto desde la lógica (y de googlear) si el siguiente no fuera cierto

a) cada instanciación de DataStoreReference es seguida en breve por un setUsage de System.currentTimeMillis) b) el elemento está marcado como no nulo en la asignación (ver a continuación) c) la tabla exportada muestra nulos solo en la columna f_external. La columna de uso tiene números largos perfectamente razonables.

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

seguido por genéricos getter/setters no modificados.

El archivo de asignación:

<?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, aquí está el código real que desencadena el problema: \t \t \t consulta Q = this.session.createQuery (Hib) \t \t \t .setString ("control", hash); \t \t \t @SuppressWarnings ("sin control") \t \t \t List referencia = q.list(); // boom – MJB

+0

Hibernate busca esto en una unión, por lo que creo que como el índice es 14, la columna probablemente se encuentre en 'DataStoreContainer'. – dasblinkenlight

+0

lógico, pero la columna mencionada en la pila es uso, que está solo en DataStoreReference. He actualizado la pregunta para incluir el otro archivo de asignación – MJB

Respuesta

2

Resulta que es un error con los dialectos Hibernate 3.6 MS SQL mejorados. Si extiende los dialectos SQLServer2005 o SQLServer2008, tendrá este problema. Usando el dialecto SQLServer anterior (que es más o menos lo que se incluye con Hibernate 3.3x) no es así. Probablemente algo relacionado con el soporte de paginación introducido. Suspiro

22

El error mensaje es claro: En al menos una fila de la f_usage columna tiene un valor nulo. Este valor nulo no se puede poner en un tipo primitivo como long, porque los tipos primitivos no pueden representar null.

El atributo no nulo en la cláusula de propiedad no tiene ningún efecto cuando ya existe un valor nulo en la base de datos. El atributo no nulo solo se usa para la generación dmd. Pero la columna f_usage de su tabla de base de datos t_dsref probablemente permita valores nulos (consulte con desc t_dsref en sql).

del intercambio de largo con Long:

private Long usage; 

y cuando se utiliza el valor que tiene para manejar la condición nula, por ejemplo

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

(Está utilizando captadores y definidores para acceder con hibernate, así que este codelet no debería estar en getter, porque en la base de datos un valor nulo debería continuar siendo nulo después de una actualización, pero puede hacerlo en un segundo getter que use en cualquier otro lado, o puede acceder al campo para hibernate .)

Mi recomendación general: los tipos de datos primitivos solo deben usarse para las propiedades de hibernación si la columna está marcada con NOT NULL en la base de datos.

+1

De acuerdo. Como una buena práctica al usar hibernate, no use tipos de datos primitivos (cambie sus valores 'long' e' int' a 'Long' y' Integer') –

+3

Esto está lejos de ser una mejor práctica. Use una primitiva cuando la columna no sea nula. Use un contenedor cuando sea anulable. –

+1

buen consejo pero --- Como noté, el archivo de mapeo tiene uso como no-nulo = verdadero. La base de datos se generó desde HIBERNaTE utilizando las utilidades de esquema incorporadas. También se verificaron los datos. No hay valores NULL en la columna de uso. La base de datos se creó desde cero utilizando hibernate y solo Hibernate lo ha poblado. – MJB

1

Hibernate necesita algunas revisiones para que coincida con los escenarios de la vida real del desarrollo empresarial. Usar objetos en lugar de primitivos conduce a muchos más problemas que los resueltos en este contexto.

He codificado aplicaciones empresariales Java EE desde 2002. La mejor solución para este caso de uso, teniendo en cuenta que probablemente tenga muchas tablas que hacen referencia a tablas de códigos con valores nulos, es actualizar la base de datos si es posible.

Por ejemplo, si tiene una tabla de personas con una referencia a una tabla de códigos de generación para indicar títulos como junior, senior, etc. y muchas entradas son nulas, actualice la tabla de códigos para tener una referencia desconocida y luego actualice datos de tabla para todos los nulos para apuntar a esa referencia. Como la mayoría de las aplicaciones Java EE que son grandes y están mal codificadas, puedes intentar actualizar los puntos de entrada a estas tablas pero lo más probable es que sea un desastre y se pueden ejecutar todo tipo de puntos de entrada desde trabajos cron, servicios web, etc. DB para capturar estos valores nulos y predeterminarlos a la entrada desconocida y ahorrarse un dolor de cabeza. Si su construcción desde cero esto también es un desastre con Hibernate, ya que no es muy fácil por lo que puedo decir para decir Hibernate es su tratando de llamar a un setter con un primitivo, y es nulo simplemente hacerlo 0 o -1, pero luego otra vez tiene menos de 20 horas de experiencia de hibernación. Acabo de leer los tipos de usuario, así que tendré que leer un poco más y ver cómo funcionan.

Los objetos en las aplicaciones Java EE grandes son una pesadilla en el tiempo de ejecución con la calidad de los codificadores en el mercado actual.

1

Tales errores suceden en Hibernate cuando se usan tipos primitivos para algunas columnas pero esos campos son nulos en DB. soluciones:

solución One: use las clases Wrapper (Entero para int ...) solución Dos: defina los valores predeterminados para las columnas.

Cuestiones relacionadas