13

Having a frustrating problem with Hibernate 3.6.9. MS SQL Server 2008. Note the exception and the odd column index reference.

The HQL Query itself:

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

The 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

Now, I'd understand this from logic (and from googling) if the following were not true

a) every instantiation of DataStoreReference is shortly followed by a setUsage of System.currentTimeMillis) b) the item is marked not-null in the mapping (see below) c) the exported table shows nulls only in the f_external column. The usage column has perfectly reasonable long numbers.

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

followed by generic unmodified getter/setters.

The mapping file:

<?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>
user2845946
  • 1,755
  • 29
  • 38
MJB
  • 9,352
  • 6
  • 34
  • 49
  • Oh here's the actual code that triggers the issue: Query q=this.session.createQuery(hib) .setString("hash",hash); @SuppressWarnings("unchecked") List reference=q.list(); //boom – MJB May 18 '12 at 03:33
  • Hibernate is fetching this in a join, so I think that because the index is 14, the column is probably in the `DataStoreContainer`. – Sergey Kalinichenko May 18 '12 at 03:37
  • logical but the column mentioned in the stack is usage, which is only in DataStoreReference. I've updated the question to include the other mapping file – MJB May 18 '12 at 03:48
  • The stack trace also says: `The value supplied cannot be converted to BIGINT`. Are you sure you have long values in this column? How is this column defined in the table? – JB Nizet May 18 '12 at 07:08
  • I will ask the beta tester. Note that the table was generated from scratch using hibernate, so it should have generated the appropriate type from the mapping file. – MJB May 18 '12 at 14:38
  • https://stackoverflow.com/questions/3154582/why-do-i-get-a-null-value-was-assigned-to-a-property-of-primitive-type-setter-o/3154585#3154585 Refer link. I got it resolved. – gnanapriya Dec 29 '15 at 05:56

4 Answers4

33

The error message is clear: In at least one row the column f_usage has a null value. This null value can't be put into a primitive type like long, because primitive types can't represent null.

The not-null attribute in the property clause has no effect when there already is a null value in the database. The not-null attribute only is used for the dmd generation. But the f_usage column of your database table t_dsref probably allows null values (check with desc t_dsref in sql).

Solution: Exchange long with Long:

private Long usage; 

and when using the value you have to handle the null condition, for example

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

(You are using getters and setters for access with hibernate, so this codelet should not be in the getter, because in the database a null value should continue to be null after an update, but you can do it in a second getter which you use everywhere else, or you do field access for hibernate.)

My general recommendation: Primitive datatypes should only be used for hibernate properties if the column is marked with NOT NULL in the database.

Johanna
  • 5,223
  • 1
  • 21
  • 38
  • 1
    Agreed. As a best practice when using hibernate, do not use primitive data types (change your `long` and `int` values to `Long` and `Integer`) – Raul Rene May 18 '12 at 09:07
  • 4
    This is far from being a best practice. Use a primitive when the column is not null. Use a wrapper when it's nullable. – JB Nizet May 18 '12 at 11:32
  • 1
    good advice but --- As I noted, the mapping file has usage as not-null=true. The database was generated from HIBERNaTE using the built in schema utilities. Also the data was checked. There are NO NULL values in the usage column. The database was created from scratch using hibernate and only hibernate has populated it. – MJB May 18 '12 at 14:37
  • 2
    @MJB: Just try one time: change the type of usage to Long and also change the parameter in the setter to Long: Does it result in a different error message then? If yes, which one? – Johanna May 18 '12 at 15:11
5

Such errors happen in Hibernate when you use primitive types for some columns but that fields are null in DB. solutions:

solution One: use Wrapper classes (Integer for int ...) solution Two: define default values for columns.

Mr.Q
  • 4,316
  • 3
  • 43
  • 40
3

Turns out it is a bug with the enhanced Hibernate 3.6 MS SQL dialects. If you extend SQLServer2005 or SQLServer2008 dialects, you will have this issue. Using the older SQLServer dialect (which is pretty much what shipped with Hibernate 3.3x) you do not. Probably something to do with paging support introduced. Sigh

MJB
  • 9,352
  • 6
  • 34
  • 49
1

Hibernate needs some revisions to match the real life scenarios of enterprise development. Using objects instead of primitives leads to many more issues than what is solved in this context.

I have been coding Java EE enterprise apps since 2002. The best solution to this use case, taking into account that you probably have many tables that reference code tables with null values is to update the database if possible.

For instance if you have a persons table with a reference to a generation code table to denote titles like junior, Senior, etc and many entries are null, update the code table to have an un-known reference and then update the table data for all nulls to point to that reference. As most Java EE apps that are large and ill-coded you can try and update the entry points to these tables but most likely it's a mess and there may be all sorts of entry points run from cron jobs, web services, etc so update the DB to catch these nulls and default them to the unknown entry and save your self a headache. If your building from scratch this is also a mess with hibernate as it's not very easy from what I can tell to tell hibernate is your trying to call a setter with a primitive, and it's null just make it 0 or -1 but then again I have less than 20 hrs of hibernate experience. I just read up on user types so I'll have to read a bit more and see how they work.

Objects in large Java EE apps are a nightmare at runtime with quality of coders on the market today.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
eric
  • 11
  • 1