com.github.marschall:hibernate-array-types

Hibernate UserTypes for binding arrays


License
MIT

Documentation

Hibernate Array Types Maven Central Javadocs

User types for binding IN lists to arrays in Hibernate 5.

<dependency>
  <groupId>com.github.marschall</groupId>
  <artifactId>hibernate-array-types</artifactId>
  <version>1.0.1</version>
</dependency>

Versions 2.x are for Hibernate 6.

Advantages

  • reduces the number of hard parses
  • improves the effectives of cursor sharing
  • works well together with client side statement caching to reduce the number of soft parses
  • supports more than 1000 parameters in IN lists in Oracle

Disadvantages

  • requires native queries with non-portable syntax
  • only a small number of databases are supported
  • works only with Hibernate, not other JPA providers
  • the API for Hibernate 6 is quite different

H2 / PostgreSQL

entityManager.createNativeQuery("""
                    SELECT u.*
                      FROM user_table u
                     WHERE u.id = ANY(:userids)
                     ORDER BY u.id
                    """, User.class)
              // you can leave out the "INTEGER" parameter and let ArrayType figure out the actual type
             .setParameter("userids", ArrayType.newParameter("INTEGER", 1, 3, 5, 7, 9))
             .getResultList()

Additionally PostgreSQL supports arrays of primitive types through the PgIntArrayType and PgLongArrayType types.

Oracle

entityManager.createNativeQuery("""
                    SELECT u.*
                      FROM user_table u
                     WHERE u.id = ANY(SELECT column_value FROM TABLE(:userids))
                     ORDER BY u.id
                    """, User.class)
             .setParameter("userids", OracleIntArrayType.newParameter("USER_ID_TYPE", 1, 3, 5, 7, 9))
             .getResultList();

You'll have to create a type of the appropriate name, for example like this

CREATE OR REPLACE TYPE USER_ID_TYPE IS TABLE OF NUMBER;

HSQLDB

entityManager.createNativeQuery("""
                    SELECT u.*
                      FROM user_table u
                     WHERE u.id IN(UNNEST(:userids))
                     ORDER BY u.id
                    """, User.class)
              // you can leave out the "INTEGER" parameter and let ArrayType figure out the actual type
             .setParameter("userids", ArrayType.newParameter("INTEGER", 1, 3, 5, 7, 9))
             .getResultList();

Tested Databases

  • H2
  • HSQLDB
  • Oracle
  • PostgreSQL

Limitations

  • Works only with native queries.
  • HSQLDB and Oracle require custom SQL syntax.
  • Supporting Oracle requires different classes and the creation of custom database types.
  • Primitive types are only supported on Oracle and PostgresSQL and require different classes.
  • Does not work with the following databases as yet do not support SQL arrays:
    • Derby
    • Firebird
    • MariaDB
    • MySQL
    • SQL Server