kaleidos / grails-postgresql-extensions

Grails plugin to use postgresql native elements such as arrays, hstores,...
Apache License 2.0
78 stars 62 forks source link

[Enhancement] Serialize Enum arrays to Integer arrays #9

Closed mattfeury closed 11 years ago

mattfeury commented 11 years ago

Hello,

in my grails app, it's very common for me to make an Enum for a domain field. GORM will serialize the Enum to its integer value/ordinal when updating the db. It will also automagically convert it to the proper Enum on deserializing (when retrieving from the db). What I do often looks like:

class User {
    static enum Role {
        ADMIN(0),
        MODERATOR(1),
        LIMITED(2)

        private final int value
        Role(int value)  { this.value = value }
        // additional enum helpers, like value() and withId(id)
    }

    Role Role
    String contents
}

what I'd like to do is to be able to use an array of enums, e.g. make the above example Role[] roles. I'd like the functionality to remain the same: serialize and deserialize to/from an integer for the db, so I think we could re-use a lot of the code from IntegerArrayType.

I managed to get the code to serialize properly by hacking the IntegerArrayType's "nullSafeSet" to look like this:

public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
    if (value == null) {
        st.setNull(index, Types.ARRAY);
    } else {
        Array array;
        Integer[] converted;
        try {
            converted = (Integer[])value;
        } catch (Exception e) {
            Object[] o = (Object[])value;
            Integer[] ints = new Integer[o.length];
            for (int i = 0; i < o.length; i++) {
                ints[i] = ((Enum)o[i]).ordinal();
            }
            converted = ints;
        }

        array = st.getConnection().createArrayOf("int", converted);
        st.setArray(index, array);
    }
}

(the code is not pretty or optimized. i was just impressed it was working).

however, i can't get the deserialization to happen. When I retrieve an item from the DB, I get a IllegalArgumentException occurred while calling setter for the field. I'm sure I have to do something in nullSafeGet, but I'm not sure what. Looking for any advice. If I figure something out, I'll make a pull request with ideally a new AbstractArrayType.

mattfeury commented 11 years ago

Think I've got something figured out that'll work here. Will make a Pull Request in the coming days to see if you think it could be included here

mattfeury commented 11 years ago

Code has been submitted for this in #10. Closing here