-->
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.  [ 3 posts ] 
Author Message
 Post subject: select-before-update problem with Oracle
PostPosted: Thu Oct 05, 2006 4:16 am 
Newbie

Joined: Thu Oct 05, 2006 3:26 am
Posts: 8
I have an application which runs on:
- Oracle 10g XE
- Tomcat 5.0.28
- Hibernate 3.1.3
- MyFaces 1.1.3

I have a simple POJO value object, which is mapped to the database
using Hibernate with dynamic-update="true" and
select-before-update="true" setting. The same value object is
binded to a JSF form, so the data is easily transferred between
the UI and the database. select-before-update enables that version
number is incremented only when there are actual changes made
by a user.

However, when there is a String field in the value object and
the field value is empty, the version number is incremented even
when there is no change.

I suspect this is because Oracle database handles NULL and an empty
string differently. JSF sets the field value to an empty string,
and Hibernate inserts the row. Oracle database converts an empty
string to NULL, so next time Hibernate fetches the field value
before updating, it fetches null and then compares with an empty
string, concluding the field is dirty.

To workaround this problem, I thought of creating a user type,
maybe by extending StringType and overriding isSame method,
but I don't know if it is the best solution.

Please help if you have any ideas.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 05, 2006 7:53 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
You are correct, a custom user type is normally used for this purpose. The think the wiki has an exact match for you.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 06, 2006 12:46 am 
Newbie

Joined: Thu Oct 05, 2006 3:26 am
Posts: 8
Thanks for the reply, David.

I have created OracleStringType which evaluates null and an empty string be equal, so null/empty string difference is considered to be dirty when using select-before-update.

It seems to work fine, but I wonder if hashCode implementation causes any problems somewhere. (null does not have hashCode, but null and an empty string is equivalent, which breaks the contracts of equals and hashCode?)


Code:
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

public class OracleStringType implements UserType {

    public OracleStringType() {
    }

    public int[] sqlTypes() {
        return new int[] { Types.VARCHAR };
    }

    public Class returnedClass() {
        return String.class;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        if ((x == y) || (x != null && y != null && x.equals(y))) return true;
        if (((x == null) || ("".equals(x))) && ((y == null) || ("".equals(y)))) return true; // null and an empty string are the equivalent
        return false;
    }

    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        return rs.getString(names[0]); // empty string is never returned from oracle
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        st.setString(index, (String)value); // empty string is converted to NULL in oracle
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public boolean isMutable() {
        return false;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (value == null) ? null : (Serializable)deepCopy(value);
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return (cached == null) ? null : deepCopy(cached);
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }

}


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