Thanks mihalcea_vlad, but that's very close to what I already have, which doesn't work.
I see 
someone else has tried defining their own type by creating a new dialect:
Code:
public class PostgreSQLDialectArray extends org.hibernate.dialect.PostgreSQLDialect{
    public PostgreSQLDialectArray() { 
        super(); 
        registerHibernateType(Types.ARRAY, "array"); 
    }
 }
But doing that doesn't work, because it results in a statement like this:
Code:
create table foo (bar array);
When in fact the array 
needs to be typed like this:
Code:
create table foo (bar integer array);
So 
registerHibernateType can't be used, because it can only map a single Type. It seems to me I need to define new int types for each type of array (float, int, string, etc) and return them from my UserType's sqlTypes function. Is that a reasonable thing to do, or is it too ugly?