-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: NullPointerException on Updating an already Deleted object
PostPosted: Wed Feb 20, 2008 10:05 pm 
Newbie

Joined: Wed Feb 20, 2008 9:49 pm
Posts: 4
So here's the general situation :) I'm trying to test / determine Hibernate's behavior when attempting to update a previously deleted object. I'd like to know that the object was deleted, but what I seem to be getting instead is a NullPointerException... there's a lot of info that I posted. It's exciting! Read on :) I would appreciate any help that you can give... all I want to do is get basic CRUD working with fairly deterministic behavior, but it doesn't seem to be cooperating.

Hibernate version:
3.2.6ga

Mapping documents:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

   <class name="com.ocpsoft.data.mocks.MockPersistentObject" table="mock_objects">
      <id name="id" column="my_id">
         <generator class="native" />
      </id>
      
      <natural-id>
         <property name="stringField" />
      </natural-id>

      <version name="version" />

      <property name="longField" />
      <property name="integerField" />
   </class>

</hibernate-mapping>


Code:
package com.ocpsoft.data.hibernate;

import org.hibernate.cfg.Configuration;

import com.ocpsoft.data.mocks.MockPersistentObject;
import com.ocpsoft.util.HibernateUtil;

public class MockOcpSoftHibernateSchema
{
    public static void init()
    {
        Configuration config = new Configuration();
        config.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        config.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
        config.setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:baseball");
        config.setProperty("hibernate.connection.username", "sa");
        config.setProperty("hibernate.connection.password", "");
        config.setProperty("hibernate.connection.pool_size", "1");
        config.setProperty("hibernate.connection.autocommit", "true");
        config.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.HashtableCacheProvider");
        config.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        config.setProperty("hibernate.show_sql", "true");

        config.setProperty("hibernate.transaction.factory_class", "org.hibernate.transaction.JDBCTransactionFactory");
        config.setProperty("hibernate.current_session_context_class", "thread");

        config.addClass(MockPersistentObject.class);

        HibernateUtil.setConfig(config);
    }
}



Code between sessionFactory.openSession() and session.close():

This is the test case that I am trying to run... and everything works, except when I call the final commit(), I get a NullPointerException instead of a "StaleObjectException" or "ObjectNotFoundException."


Code:
    @Test(expected = NoSuchObjectException.class)
    public void testCannotUpdateNonexistentObject() throws DuplicateObjectException, NoSuchObjectException
    {
        try
        {
            Transaction trans = this.dao.beginTransaction();
            this.dao.deleteAll();
            trans.commit();

            trans = this.dao.beginTransaction();
            MockPersistentObject entity = new MockPersistentObject();
            entity.setIntegerField(1);
            entity.setLongField(new Long(1));
            entity.setStringField("value1");
            entity = this.dao.create(entity);
            trans.commit();

            trans = this.dao.beginTransaction();
            this.dao.delete(entity);
            trans.commit();

            entity.setIntegerField(234);
            trans = this.dao.beginTransaction();
            this.dao.update(entity);
            trans.commit();
        }
        catch (NoSuchObjectException e)
        {
            HibernateUtil.closeSession();
            throw e;
        }
    }


The relevant related code:
Code:
package com.ocpsoft.data.transaction;

import org.hibernate.Session;

import com.ocpsoft.data.Transaction;
import com.ocpsoft.util.HibernateUtil;

public class HibernateTransaction implements Transaction
{
    Session session;

    public HibernateTransaction()
    {
        this.session = HibernateUtil.currentSession();
        if (this.session.isOpen() && this.session.getTransaction().isActive())
        {
            throw new TransactionException("An active transaction already exists.");
        }

        this.session = HibernateUtil.currentSession();
        this.session.beginTransaction();
    }

    public void commit()
    {
        try
        {
            this.session.getTransaction().commit();
        }
        catch (RuntimeException e)
        {
            this.rollback();
            throw e;
        }
        finally
        {
            this.session = HibernateUtil.currentSession();
        }
    }

    public void rollback()
    {
        try
        {
            this.session.getTransaction().rollback();
        }
        catch (RuntimeException e)
        {
            throw e;
        }
        finally
        {
            this.session = HibernateUtil.currentSession();
        }
    }

}


The Dao:
Code:
package com.ocpsoft.data.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.exception.ConstraintViolationException;

import com.ocpsoft.data.Dao;
import com.ocpsoft.data.PersistentObject;
import com.ocpsoft.data.Transaction;
import com.ocpsoft.data.transaction.HibernateTransaction;
import com.ocpsoft.exceptions.DuplicateObjectException;
import com.ocpsoft.exceptions.NoSuchObjectException;
import com.ocpsoft.util.HibernateUtil;

abstract public class AbstractHibernateDao<T extends PersistentObject> implements Dao<T, Serializable>
{
    private Class<T> persistentClass;

    protected AbstractHibernateDao(final Class<T> type)
    {
        this.persistentClass = type;
    }

    public Transaction beginTransaction()
    {
        return new HibernateTransaction();
    }

    @SuppressWarnings("unchecked")
    public T create(final T entity) throws DuplicateObjectException
    {
        try
        {
            this.getSession().save(entity);
            this.getSession().flush();
        }
        catch (ConstraintViolationException e)
        {
            throw new DuplicateObjectException(e);
        }
        return entity;
    }

    public void delete(final T entity) throws NoSuchObjectException
    {
        try
        {
            if (entity.getId() instanceof Long)
            {
                this.getSession().delete(entity);
                this.getSession().flush();
            }
            else
            {
                throw new RuntimeException("Object to be deleted must have a set Id");
            }
        }
        catch (StaleObjectStateException e)
        {
            throw new NoSuchObjectException(e);
        }
    }

    @Override
    public List<T> deleteAll()
    {
        try
        {
            List<T> list = this.findAll();
            for (T obj : list)
            {
                this.delete(obj);
            }
            return list;
        }
        catch (NoSuchObjectException e)
        {
            throw new RuntimeException("Object became stale during operation", e);
        }
    }

    @Override
    public List<T> deleteByExample(final T exampleInstance)
    {
        try
        {
            List<T> list = this.findByExample(exampleInstance);
            for (T obj : list)
            {
                this.delete(obj);
            }
            return list;
        }
        catch (NoSuchObjectException e)
        {
            throw new RuntimeException("Object became stale during operation, e");
        }
    }

    @Override
    public List<T> deleteByExample(final T exampleInstance, final String... excludeProperty)
    {
        try
        {
            List<T> list = this.findByExample(exampleInstance, excludeProperty);
            for (T obj : list)
            {
                this.delete(obj);
            }
            return list;
        }
        catch (NoSuchObjectException e)
        {
            throw new RuntimeException("Object became stale during operation, e");
        }
    }

    @SuppressWarnings("unchecked")
    public List<T> findAll()
    {
        return this.findByCriteria();
    }

    @SuppressWarnings("unchecked")
    protected List<T> findByCriteria(final Criterion... criterion)
    {
        Criteria crit = this.getSession().createCriteria(this.getPersistentClass());
        for (Criterion c : criterion)
        {
            crit.add(c);
        }
        return crit.list();
    }

    @SuppressWarnings("unchecked")
    public List<T> findByExample(final T exampleInstance)
    {
        Criteria criteria = this.getSession().createCriteria(this.getPersistentClass());
        criteria.add(Example.create(exampleInstance).excludeZeroes());
        return criteria.list();
    }

    @SuppressWarnings("unchecked")
    public List<T> findByExample(final T exampleInstance, final String... excludeProperty)
    {
        Criteria crit = this.getSession().createCriteria(this.getPersistentClass());
        Example example = Example.create(exampleInstance);
        for (String exclude : excludeProperty)
        {
            example.excludeProperty(exclude);
        }
        crit.add(example);
        return crit.list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public T findById(final Serializable id) throws NoSuchObjectException
    {
        T entity;
        try
        {
            entity = (T) this.getSession().load(this.getPersistentClass(), id, LockMode.UPGRADE);
            return entity;
        }
        catch (ObjectNotFoundException e)
        {
            throw new NoSuchObjectException(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public T findUnique(final T exampleInstance) throws NoSuchObjectException, InvalidResultException
    {
        T result = null;
        Criteria criteria = this.getSession().createCriteria(this.getPersistentClass());
        criteria.add(Example.create(exampleInstance).excludeZeroes());
        List<T> rows = criteria.list();
        if ((rows instanceof List) && (rows.size() == 1))
        {
            result = rows.get(0);
        }
        else if (((rows instanceof List) && (rows.size() == 0)))
        {
            throw new NoSuchObjectException("No such record exists in the database");
        }
        else
        {
            throw new InvalidResultException("More than one record matched");
        }
        return result;
    }

    private Class<T> getPersistentClass()
    {
        return this.persistentClass;
    }

    protected Session getSession()
    {
        return HibernateUtil.currentSession();
    }

    @Override
    public void update(final T entity) throws NoSuchObjectException
    {
        try
        {
            this.getSession().update(entity);
        }
        catch (StaleObjectStateException e)
        {
            throw new NoSuchObjectException(e);
        }
    }

}


Full stack trace of any exception that occurs:
Code:
java.lang.Exception: Unexpected exception, expected<com.ocpsoft.exceptions.NoSuchObjectException> but was<java.lang.NullPointerException>
   at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:91)
   at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
   at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
   at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
   at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
   at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
   at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
   at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
   at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.lang.NullPointerException
   at org.hibernate.event.def.DefaultFlushEntityEventListener.checkNaturalId(DefaultFlushEntityEventListener.java:89)
   at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:169)
   at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:120)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:196)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at com.ocpsoft.data.transaction.HibernateTransaction.commit(HibernateTransaction.java:29)
   at com.ocpsoft.data.dao.AbstractHibernateDaoTest.testCannotUpdateNonexistentObject(AbstractHibernateDaoTest.java:521)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
   at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
   ... 14 more


Name and version of the database you are using:
Java Derby DB

The generated SQL (show_sql=true):

Debug level Hibernate log excerpt:
Code:
20:49:14,474  INFO Environment:514 - Hibernate 3.2.6
20:49:14,482  INFO Environment:547 - hibernate.properties not found
20:49:14,486  INFO Environment:681 - Bytecode provider name : cglib
20:49:14,497  INFO Environment:598 - using JDK 1.4 java.sql.Timestamp handling
20:49:14,575  INFO Configuration:591 - Reading mappings from resource: com/ocpsoft/data/mocks/MockPersistentObject.hbm.xml
20:49:14,576  INFO Configuration:536 - Reading mappings from resource: com/ocpsoft/data/mocks/MockPersistentObject.hbm.xml
20:49:14,818  INFO HbmBinder:300 - Mapping class: com.ocpsoft.data.mocks.MockPersistentObject -> mock_objects
20:49:14,913  INFO DriverManagerConnectionProvider:41 - Using Hibernate built-in connection pool (not for production use!)
20:49:14,914  INFO DriverManagerConnectionProvider:42 - Hibernate connection pool size: 1
20:49:14,914  INFO DriverManagerConnectionProvider:45 - autocommit mode: true
20:49:14,920  INFO DriverManagerConnectionProvider:80 - using driver: org.hsqldb.jdbcDriver at URL: jdbc:hsqldb:mem:baseball
20:49:14,921  INFO DriverManagerConnectionProvider:86 - connection properties: {user=sa, password=****, autocommit=true}
20:49:15,117  INFO SettingsFactory:89 - RDBMS: HSQL Database Engine, version: 1.8.0
20:49:15,118  INFO SettingsFactory:90 - JDBC driver: HSQL Database Engine Driver, version: 1.8.0
20:49:15,133  INFO Dialect:152 - Using dialect: org.hibernate.dialect.HSQLDialect
20:49:15,138  INFO TransactionFactoryFactory:34 - Transaction strategy: org.hibernate.transaction.JDBCTransactionFactory
20:49:15,141  INFO TransactionManagerLookupFactory:33 - No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
20:49:15,141  INFO SettingsFactory:143 - Automatic flush during beforeCompletion(): disabled
20:49:15,142  INFO SettingsFactory:147 - Automatic session close at end of transaction: disabled
20:49:15,142  INFO SettingsFactory:154 - JDBC batch size: 15
20:49:15,143  INFO SettingsFactory:157 - JDBC batch updates for versioned data: disabled
20:49:15,144  INFO SettingsFactory:162 - Scrollable result sets: enabled
20:49:15,144  INFO SettingsFactory:170 - JDBC3 getGeneratedKeys(): disabled
20:49:15,145  INFO SettingsFactory:178 - Connection release mode: auto
20:49:15,146  INFO SettingsFactory:205 - Default batch fetch size: 1
20:49:15,146  INFO SettingsFactory:209 - Generate SQL with comments: disabled
20:49:15,147  INFO SettingsFactory:213 - Order SQL updates by primary key: disabled
20:49:15,147  INFO SettingsFactory:217 - Order SQL inserts for batching: disabled
20:49:15,147  INFO SettingsFactory:386 - Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
20:49:15,150  INFO ASTQueryTranslatorFactory:24 - Using ASTQueryTranslatorFactory
20:49:15,150  INFO SettingsFactory:225 - Query language substitutions: {}
20:49:15,151  INFO SettingsFactory:230 - JPA-QL strict compliance: disabled
20:49:15,151  INFO SettingsFactory:235 - Second-level cache: enabled
20:49:15,152  INFO SettingsFactory:239 - Query cache: disabled
20:49:15,152  INFO SettingsFactory:373 - Cache provider: org.hibernate.cache.HashtableCacheProvider
20:49:15,154  INFO SettingsFactory:254 - Optimize cache for minimal puts: disabled
20:49:15,154  INFO SettingsFactory:263 - Structured second-level cache entries: disabled
20:49:15,159  INFO SettingsFactory:283 - Echoing all SQL to stdout
20:49:15,159  INFO SettingsFactory:290 - Statistics: disabled
20:49:15,160  INFO SettingsFactory:294 - Deleted entity synthetic identifier rollback: disabled
20:49:15,160  INFO SettingsFactory:309 - Default entity-mode: pojo
20:49:15,160  INFO SettingsFactory:313 - Named query checking : enabled
20:49:15,199  INFO SessionFactoryImpl:161 - building session factory
20:49:15,449  INFO SessionFactoryObjectFactory:82 - Not binding factory to JNDI, no JNDI name configured
20:49:15,453  INFO SchemaExport:154 - Running hbm2ddl schema export
20:49:15,455 DEBUG SchemaExport:170 - import file not found: /import.sql
20:49:15,455  INFO SchemaExport:179 - exporting generated schema to database
20:49:15,456 DEBUG SchemaExport:303 - drop table mock_objects if exists
20:49:15,457 DEBUG SchemaExport:303 - create table mock_objects (my_id bigint generated by default as identity (start with 1), version integer not null, stringField varchar(255) not null, longField bigint, integerField integer, primary key (my_id), unique (stringField))
20:49:15,464  INFO SchemaExport:196 - schema export complete
20:49:15,578 DEBUG JDBCTransaction:54 - begin
20:49:15,579 DEBUG JDBCTransaction:59 - current autocommit status: true
20:49:15,579 DEBUG JDBCTransaction:62 - disabling autocommit
Hibernate: select this_.my_id as my1_0_0_, this_.version as version0_0_, this_.stringField as stringFi3_0_0_, this_.longField as longField0_0_, this_.integerField as integerF5_0_0_ from mock_objects this_
20:49:15,602 DEBUG JDBCTransaction:103 - commit
20:49:15,602 DEBUG JDBCTransaction:193 - re-enabling autocommit
20:49:15,602 DEBUG JDBCTransaction:116 - committed JDBC Connection
20:49:15,605 DEBUG JDBCTransaction:54 - begin
20:49:15,606 DEBUG JDBCTransaction:59 - current autocommit status: true
20:49:15,606 DEBUG JDBCTransaction:62 - disabling autocommit
Hibernate: insert into mock_objects (my_id, version, stringField, longField, integerField) values (null, ?, ?, ?, ?)
Hibernate: call identity()
20:49:15,626 DEBUG JDBCTransaction:103 - commit
20:49:15,627 DEBUG JDBCTransaction:193 - re-enabling autocommit
20:49:15,627 DEBUG JDBCTransaction:116 - committed JDBC Connection
20:49:15,628 DEBUG JDBCTransaction:54 - begin
20:49:15,628 DEBUG JDBCTransaction:59 - current autocommit status: true
20:49:15,629 DEBUG JDBCTransaction:62 - disabling autocommit
Hibernate: delete from mock_objects where my_id=? and version=?
20:49:15,641 DEBUG JDBCTransaction:103 - commit
20:49:15,641 DEBUG JDBCTransaction:193 - re-enabling autocommit
20:49:15,642 DEBUG JDBCTransaction:116 - committed JDBC Connection
20:49:15,642 DEBUG JDBCTransaction:54 - begin
20:49:15,643 DEBUG JDBCTransaction:59 - current autocommit status: true
20:49:15,643 DEBUG JDBCTransaction:62 - disabling autocommit
20:49:15,644 DEBUG JDBCTransaction:103 - commit
Hibernate: select mockpersis_.stringField as stringFi3_0_ from mock_objects mockpersis_ where mockpersis_.my_id=?
20:49:15,645 DEBUG JDBCTransaction:152 - rollback
20:49:15,646 DEBUG JDBCTransaction:193 - re-enabling autocommit
20:49:15,646 DEBUG JDBCTransaction:163 - rolled back JDBC Connection


Problems with Session and transaction handling?
Yep! I think I'm doing somethin' wrong!!! Please help!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 21, 2008 4:48 pm 
Newbie

Joined: Wed Feb 20, 2008 9:49 pm
Posts: 4
It might also be worth mentioning, that I am very novice with Hibernate at the moment. I've probably done something wrong, but all I want to accomplish is to know the specific error that is passed back from the JDBC at the time of the update() call.

I don't want to have to wait until I commit() the transaction to get a "NoSuchObjectException".


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 18, 2008 10:12 am 
Newbie

Joined: Fri Jul 18, 2008 9:47 am
Posts: 1
One point that I thought might be worth raising is that you state your using Derby, but the Hibernate config your generating specifies a HSQLDB driver and Dialect.


Top
 Profile  
 
 Post subject: Re: NullPointerException on Updating an already Deleted object
PostPosted: Tue Sep 13, 2011 4:57 am 
Newbie

Joined: Sat Sep 03, 2011 10:16 am
Posts: 10
I'm also being hit by this problem. The thing is, that once this exception is thrown, Hibernate never recovers from it. Any further calls also result in this exception.

In my app, I have the ability to open the same Order twice. If in one order window I click "Delete", and then in the other one I click "Save Changes", then I get the exception.

The two Order entities that are passed to these windows are created in different sessions, so they are both detached.

I tried changing saveOrUpdate() to merge() and that fixed the error, but merge() is not what I want in this case.


Top
 Profile  
 
 Post subject: Re: NullPointerException on Updating an already Deleted object
PostPosted: Wed Sep 14, 2011 7:22 am 
Newbie

Joined: Wed Sep 14, 2011 7:18 am
Posts: 1
adsdasdasf

_________________
Taos ski valley - Recessed Lighting - Taos Real estate


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.