-->
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.  [ 7 posts ] 
Author Message
 Post subject: updating object on save/update
PostPosted: Wed Dec 22, 2004 12:54 pm 
Newbie

Joined: Tue Nov 23, 2004 8:19 am
Posts: 12
Location: Santa Maria-RS, Brazil
Hi

I'd like to update objects before they are saved or updated. I have to create/update tables from a legacy database that have columns for the date/time of the last update (every table); so I'd like to do that in a single point. As I'm using hibernate3-beta1, what's the best way to do that?

I've tryed to do that: I created an abstract super-class with the properties for those columns; so I extended org.hibernate.event.DefaultSaveEventListener, and for each object of that class, the onSaveOrUpdate() method updates the properties.

However, the onSaveOrUpdate() method is called but I get an SQLException (because the columns are not null), what means that the object wasn't updated (or the values for the INSERT statement were got before the onSaveOrUpdate() method was called?).

I also thought about implementing org.hibernate.Interceptor and doing that in the onSave() method, but it requires changes in my infrastructure code. Would I get luck this way?

thx


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2004 1:30 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
why does interceptor require changes to the infrastructure code ?

intereceptor is the recommend way for the date updates in hibernate code.

the event stuff is more lowlevel (but should also work imo...do you remember to call super.themethodyouhaveoverwritten() ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2004 1:47 pm 
Newbie

Joined: Tue Nov 23, 2004 8:19 am
Posts: 12
Location: Santa Maria-RS, Brazil
thx max

The interceptor changes my web infrastructure code because I have classes that open a session for each web request (storing it as ThreadLocal) and manage the transactions. So I don't have to worry about configuring session factory, opening sessions and commiting transactions.

However, currently that infrastructure doesn't support interceptors; so, if I REALLY need to use them, I'll need to change the infrastructure code. That is why I tryed the listener before.

Yes, I did remembered to call super.onSaveOrUpdate(). I'll write a short example code to send to the forum. Maybe there is a bug in hibernate to be fixed, or I'm just missing sth... In both cases, it's worth to write an example.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2004 3:03 pm 
Newbie

Joined: Tue Nov 23, 2004 8:19 am
Posts: 12
Location: Santa Maria-RS, Brazil
Ok, now I got an example. Sorry, the table and column names are in portuguese, but I think it won't be a problem.

Person objects (POJO) have these properties:
Code:
    private String name;
    private long id = -1;
    private int version = -1, userCode;
    private Date updateDate, updateTime;


The listener code:
Code:
package br.ufsm.cpd.sg;
public class SaveUpdateListener extends org.hibernate.event.DefaultSaveEventListener{
    public java.io.Serializable onSaveOrUpdate(org.hibernate.event.SaveOrUpdateEvent event){
        if (event.getObject() instanceof Person){
            Person p = (Person) event.getObject();
            p.setUserCode(1);
            java.util.Date now = new java.util.Date();
            p.setUpdateDate(now);
            p.setUpdateTime(now);
        }
        return super.onSaveOrUpdate(event);
    }
}


The hibernate mapping (remember: all columns are not null):
Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="jdbc.fetch_size">10</property>
        <property name="jdbc.batch_size">0</property>

        <property name="hibernate.dialect">org.hibernate.dialect.DB2Dialect</property>
        <property name="hibernate.connection.driver_class">com.ibm.db2.jcc.DB2Driver</property>
        <property name="hibernate.connection.url">jdbc:db2://localhost:50000/dbsmdev</property>
        <property name="hibernate.connection.username">dbuser</property>
        <property name="hibernate.connection.password">password</property>

        <property name="hibernate.connection.provider_class">
org.hibernate.connection.DriverManagerConnectionProvider</property>
        <property name="hibernate.query.substitutions">TRUE=1, FALSE=0</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.use_sql_comments">false</property>
        <property name="hibernate.generate_statistics">false</property>

        <mapping resource="br/ufsm/cpd/sg/Person.hbm.xml"/>

        <listener type="save-update" class="br.ufsm.cpd.sg.SaveUpdateListener"/>
    </session-factory>
</hibernate-configuration>

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

<hibernate-mapping package="br.ufsm.cpd.sg">
    <class name="Person" table="PESSOAS" discriminator-value="F">

        <id name="id" column="ID_PESSOA" unsaved-value="-1">
            <generator class="increment"/>
        </id>
        <discriminator column="NATUREZA_JURIDICA" type="character"/>

        <version name="version" column="CONCORRENCIA" unsaved-value="negative"/>
        <property name="updateDate" column="DT_ALTERACAO" type="date"/>
        <property name="updateTime" column="HR_ALTERACAO" type="time"/>
        <property name="userCode" column="COD_OPERADOR"/>

        <property name="name" column="NOME_PESSOA" length="60"/>
    </class>
</hibernate-mapping>


The test code:
Code:
package br.ufsm.cpd.sg;
import br.ufsm.cpd.commons.hibernate.Hibernate3Session;

public class ListenerTest extends junit.framework.TestCase {

    public void setUp() throws Exception {
        super.setUp();
        org.hibernate.SessionFactory fac = new org.hibernate.cfg.Configuration()
                .configure().buildSessionFactory();
        //Configures the sessionfactory in the ThreadLocal
        Hibernate3Session.configure(fac);
        //currentSession() gets the session from another ThreadLocal
        Hibernate3Session.currentSession().connection().setAutoCommit(false);
    }

    public void tearDown() throws Exception {
        Hibernate3Session.flush();
//        Hibernate3Session.currentSession().connection().commit();
        Hibernate3Session.currentSession().connection().rollback();
        Hibernate3Session.close();
        super.tearDown();
    }

    public void testSave() {
        Person p = new Person();
        p.setName("John");
        Hibernate3Session.currentSession().save(p);
    }
}


That's it! I got a contraint violation when I run testSave(). Is it a hibernate bug or am I doing anything wrong?

thx


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2004 3:44 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
what is the stacktrace of the constraint violation ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2004 4:12 pm 
Newbie

Joined: Tue Nov 23, 2004 8:19 am
Posts: 12
Location: Santa Maria-RS, Brazil
Max

Here is the log. The exception is thrown after the call to session.flush() (Hibernate3Session.flush() takes the session from the ThreadLocal and call flush if it's not null).

The message in portuguese (A atribuição de um valor NULL a uma coluna NOT NULL "TBSPACEID=7, TABLEID=40, COLNO=4" não é permitida) means: Setting a NULL value to a NOT NULL column "TBSPACEID=7, TABLEID=40, COLNO=4" isn't allowed.
Code:
22/12/2004 17:55:12 org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.0 beta 1
22/12/2004 17:55:12 org.hibernate.cfg.Environment <clinit>
INFO: loaded properties from resource hibernate.properties: {hibernate.cglib.use_reflection_optimizer=true, hibernate.jdbc.use_streams_for_binary=true}
22/12/2004 17:55:12 org.hibernate.cfg.Environment <clinit>
INFO: using java.io streams to persist binary types
22/12/2004 17:55:12 org.hibernate.cfg.Environment <clinit>
INFO: using CGLIB reflection optimizer
22/12/2004 17:55:12 org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
22/12/2004 17:55:12 org.hibernate.cfg.Configuration configure
INFO: configuring from resource: /hibernate.cfg.xml
22/12/2004 17:55:12 org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: Configuration resource: /hibernate.cfg.xml
22/12/2004 17:55:13 org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: br/ufsm/cpd/sg/Person.hbm.xml
22/12/2004 17:55:13 org.hibernate.cfg.HbmBinder bindRootClass
INFO: Mapping class: br.ufsm.cpd.sg.Person -> PESSOAS
22/12/2004 17:55:13 org.hibernate.cfg.Configuration doConfigure
INFO: Configured SessionFactory: null
22/12/2004 17:55:13 org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
22/12/2004 17:55:13 org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
22/12/2004 17:55:13 org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
22/12/2004 17:55:13 org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
22/12/2004 17:55:13 org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.DB2Dialect
22/12/2004 17:55:13 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
22/12/2004 17:55:13 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
22/12/2004 17:55:13 org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.classic.ClassicQueryTranslatorFactory
22/12/2004 17:55:13 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {TRUE=1, FALSE=0}
22/12/2004 17:55:13 org.hibernate.connection.ConnectionProviderFactory newConnectionProvider
INFO: Initializing connection provider: org.hibernate.connection.DriverManagerConnectionProvider
22/12/2004 17:55:13 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
22/12/2004 17:55:13 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 20
22/12/2004 17:55:13 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: false
22/12/2004 17:55:13 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: com.ibm.db2.jcc.DB2Driver at URL: jdbc:db2://localhost.br:50000/dbsmdev
22/12/2004 17:55:13 org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=dbuser, password=****}
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): disabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC result set fetch size: 10
22/12/2004 17:55:14 org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
22/12/2004 17:55:14 org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.EhCacheProvider
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
22/12/2004 17:55:14 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
22/12/2004 17:55:14 org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
22/12/2004 17:55:14 net.sf.ehcache.config.Configurator configure
WARNING: No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/home/rgmoro/.maven/repository/ehcache/jars/ehcache-0.9.jar!/ehcache-failsafe.xml
22/12/2004 17:55:15 org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
22/12/2004 17:55:15 org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
Hibernate: insert into PESSOAS (CONCORRENCIA, DT_ALTERACAO, HR_ALTERACAO, COD_OPERADOR, NOME_PESSOA, NATUREZA_JURIDICA, ID_PESSOA) values (?, ?, ?, ?, ?, 'F', ?)
22/12/2004 17:55:15 org.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: -407, SQLState: 23502
22/12/2004 17:55:16 org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: A atribuição de um valor NULL a uma coluna NOT NULL "TBSPACEID=7, TABLEID=40, COLNO=4" não é permitida.
22/12/2004 17:55:16 org.hibernate.event.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: could not insert: [br.ufsm.cpd.sg.Person]
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:63)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.persister.BasicEntityPersister.insert(BasicEntityPersister.java:1683)
   at org.hibernate.persister.BasicEntityPersister.insert(BasicEntityPersister.java:2012)
   at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:42)
   at org.hibernate.impl.ActionQueue.executeActions(ActionQueue.java:232)
   at org.hibernate.impl.ActionQueue.executeActions(ActionQueue.java:137)
   at org.hibernate.event.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:255)
   at org.hibernate.event.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:814)
   at br.ufsm.cpd.commons.hibernate.Hibernate3Session.flush(Hibernate3Session.java:121)
   at br.ufsm.cpd.sg.ListenerTest.tearDown(ListenerTest.java:18)
   at junit.framework.TestCase.runBare(TestCase.java:130)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:118)
   at junit.framework.TestSuite.runTest(TestSuite.java:208)
   at junit.framework.TestSuite.run(TestSuite.java:203)
   at junit.textui.TestRunner.doRun(TestRunner.java:116)
   at com.intellij.rt.execution.junit2.IdeaJUnitAgent.doRun(IdeaJUnitAgent.java:57)
   at junit.textui.TestRunner.start(TestRunner.java:172)
   at com.intellij.rt.execution.junit.TextTestRunner2.startRunnerWithArgs(TextTestRunner2.java:23)
   at com.intellij.rt.execution.junit2.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:97)
   at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
   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:585)
   at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
Caused by: com.ibm.db2.jcc.b.SQLException: A atribuição de um valor NULL a uma coluna NOT NULL "TBSPACEID=7, TABLEID=40, COLNO=4" não é permitida.
   at com.ibm.db2.jcc.b.ce.d(ce.java:975)
   at com.ibm.db2.jcc.a.bd.k(bd.java:312)
   at com.ibm.db2.jcc.a.bd.a(bd.java:61)
   at com.ibm.db2.jcc.a.r.a(r.java:64)
   at com.ibm.db2.jcc.a.bq.c(bq.java:217)
   at com.ibm.db2.jcc.b.cf.C(cf.java:1109)
   at com.ibm.db2.jcc.b.cf.a(cf.java:1505)
   at com.ibm.db2.jcc.b.cf.executeUpdate(cf.java:322)
   at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:22)
   at org.hibernate.persister.BasicEntityPersister.insert(BasicEntityPersister.java:1667)
   ... 27 more

org.hibernate.exception.ConstraintViolationException: could not insert: [br.ufsm.cpd.sg.Person]
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:63)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.persister.BasicEntityPersister.insert(BasicEntityPersister.java:1683)
   at org.hibernate.persister.BasicEntityPersister.insert(BasicEntityPersister.java:2012)
   at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:42)
   at org.hibernate.impl.ActionQueue.executeActions(ActionQueue.java:232)
   at org.hibernate.impl.ActionQueue.executeActions(ActionQueue.java:137)
   at org.hibernate.event.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:255)
   at org.hibernate.event.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:814)
   at br.ufsm.cpd.commons.hibernate.Hibernate3Session.flush(Hibernate3Session.java:121)
   at br.ufsm.cpd.sg.ListenerTest.tearDown(ListenerTest.java:18)
   at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
Caused by: com.ibm.db2.jcc.b.SQLException: A atribuição de um valor NULL a uma coluna NOT NULL "TBSPACEID=7, TABLEID=40, COLNO=4" não é permitida.
   at com.ibm.db2.jcc.b.ce.d(ce.java:975)
   at com.ibm.db2.jcc.a.bd.k(bd.java:312)
   at com.ibm.db2.jcc.a.bd.a(bd.java:61)
   at com.ibm.db2.jcc.a.r.a(r.java:64)
   at com.ibm.db2.jcc.a.bq.c(bq.java:217)
   at com.ibm.db2.jcc.b.cf.C(cf.java:1109)
   at com.ibm.db2.jcc.b.cf.a(cf.java:1505)
   at com.ibm.db2.jcc.b.cf.executeUpdate(cf.java:322)
   at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:22)
   at org.hibernate.persister.BasicEntityPersister.insert(BasicEntityPersister.java:1667)
   ... 27 more


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 22, 2004 5:12 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
i will encourage you to try to step in with a debugger (or enable more debug logging) and see what the diff is between running it with or without your custom event stuff..

_________________
Max
Don't forget to rate


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.